diff options
Diffstat (limited to 'libs/utils')
-rw-r--r-- | libs/utils/Android.mk | 1 | ||||
-rw-r--r-- | libs/utils/LinearTransform.cpp | 9 | ||||
-rw-r--r-- | libs/utils/Log.cpp | 37 | ||||
-rw-r--r-- | libs/utils/SystemClock.cpp | 92 | ||||
-rw-r--r-- | libs/utils/Timers.cpp | 3 | ||||
-rw-r--r-- | libs/utils/Trace.cpp | 4 | ||||
-rw-r--r-- | libs/utils/VectorImpl.cpp | 48 | ||||
-rw-r--r-- | libs/utils/ZipFileRO.cpp | 60 | ||||
-rw-r--r-- | libs/utils/ZipUtils.cpp | 10 | ||||
-rw-r--r-- | libs/utils/misc.cpp | 102 | ||||
-rw-r--r-- | libs/utils/tests/Android.mk | 42 |
11 files changed, 208 insertions, 200 deletions
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk index ddfb83e..c9f8fd4 100644 --- a/libs/utils/Android.mk +++ b/libs/utils/Android.mk @@ -26,6 +26,7 @@ commonSources:= \ FileMap.cpp \ Flattenable.cpp \ LinearTransform.cpp \ + Log.cpp \ PropertyMap.cpp \ RefBase.cpp \ SharedBuffer.cpp \ diff --git a/libs/utils/LinearTransform.cpp b/libs/utils/LinearTransform.cpp index d752415..b7d28d4 100644 --- a/libs/utils/LinearTransform.cpp +++ b/libs/utils/LinearTransform.cpp @@ -114,6 +114,7 @@ static bool linear_transform_s64_to_s64( int64_t basis1, int32_t N, uint32_t D, + bool invert_frac, int64_t basis2, int64_t* out) { uint64_t scaled, res; @@ -137,8 +138,8 @@ static bool linear_transform_s64_to_s64( is_neg = !is_neg; if (!scale_u64_to_u64(abs_val, - ABS(N), - D, + invert_frac ? D : ABS(N), + invert_frac ? ABS(N) : D, &scaled, is_neg)) return false; // overflow/undeflow @@ -191,6 +192,7 @@ bool LinearTransform::doForwardTransform(int64_t a_in, int64_t* b_out) const { a_zero, a_to_b_numer, a_to_b_denom, + false, b_zero, b_out); } @@ -201,8 +203,9 @@ bool LinearTransform::doReverseTransform(int64_t b_in, int64_t* a_out) const { return linear_transform_s64_to_s64(b_in, b_zero, - a_to_b_denom, a_to_b_numer, + a_to_b_denom, + true, a_zero, a_out); } diff --git a/libs/utils/Log.cpp b/libs/utils/Log.cpp new file mode 100644 index 0000000..bffb56e --- /dev/null +++ b/libs/utils/Log.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012 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. + */ + +#define LOG_TAG "Log" + +#include <utils/Log.h> +#include <utils/Timers.h> + +namespace android { + +LogIfSlow::LogIfSlow(const char* tag, android_LogPriority priority, + int timeoutMillis, const char* message) : + mTag(tag), mPriority(priority), mTimeoutMillis(timeoutMillis), mMessage(message), + mStart(systemTime(SYSTEM_TIME_BOOTTIME)) { +} + +LogIfSlow::~LogIfSlow() { + int durationMillis = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_BOOTTIME) - mStart); + if (durationMillis > mTimeoutMillis) { + LOG_PRI(mPriority, mTag, "%s: %dms", mMessage, durationMillis); + } +} + +} // namespace android diff --git a/libs/utils/SystemClock.cpp b/libs/utils/SystemClock.cpp index 8b8ac10..ec2d82e 100644 --- a/libs/utils/SystemClock.cpp +++ b/libs/utils/SystemClock.cpp @@ -106,7 +106,74 @@ int64_t uptimeMillis() */ int64_t elapsedRealtime() { + return nanoseconds_to_milliseconds(elapsedRealtimeNano()); +} + +#define METHOD_CLOCK_GETTIME 0 +#define METHOD_IOCTL 1 +#define METHOD_SYSTEMTIME 2 + +static const char *gettime_method_names[] = { + "clock_gettime", + "ioctl", + "systemTime", +}; + +static inline void checkTimeStamps(int64_t timestamp, + int64_t volatile *prevTimestampPtr, + int volatile *prevMethodPtr, + int curMethod) +{ + /* + * Disable the check for SDK since the prebuilt toolchain doesn't contain + * gettid, and int64_t is different on the ARM platform + * (ie long vs long long). + */ +#ifdef ARCH_ARM + int64_t prevTimestamp = *prevTimestampPtr; + int prevMethod = *prevMethodPtr; + + if (timestamp < prevTimestamp) { + ALOGW("time going backwards: prev %lld(%s) vs now %lld(%s), tid=%d", + prevTimestamp, gettime_method_names[prevMethod], + timestamp, gettime_method_names[curMethod], + gettid()); + } + // NOTE - not atomic and may generate spurious warnings if the 64-bit + // write is interrupted or not observed as a whole. + *prevTimestampPtr = timestamp; + *prevMethodPtr = curMethod; +#endif +} + +/* + * native public static long elapsedRealtimeNano(); + */ +int64_t elapsedRealtimeNano() +{ #ifdef HAVE_ANDROID_OS + struct timespec ts; + int result; + int64_t timestamp; + static volatile int64_t prevTimestamp; + static volatile int prevMethod; + +#if 0 + /* + * b/7100774 + * clock_gettime appears to have clock skews and can sometimes return + * backwards values. Disable its use until we find out what's wrong. + */ + result = clock_gettime(CLOCK_BOOTTIME, &ts); + if (result == 0) { + timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec; + checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, + METHOD_CLOCK_GETTIME); + return timestamp; + } +#endif + + // CLOCK_BOOTTIME doesn't exist, fallback to /dev/alarm static int s_fd = -1; if (s_fd == -1) { @@ -116,23 +183,24 @@ int64_t elapsedRealtime() } } - struct timespec ts; - int result = ioctl(s_fd, + result = ioctl(s_fd, ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts); if (result == 0) { - int64_t when = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec; - return (int64_t) nanoseconds_to_milliseconds(when); - } else { - // XXX: there was an error, probably because the driver didn't - // exist ... this should return - // a real error, like an exception! - int64_t when = systemTime(SYSTEM_TIME_MONOTONIC); - return (int64_t) nanoseconds_to_milliseconds(when); + timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec; + checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, METHOD_IOCTL); + return timestamp; } + + // XXX: there was an error, probably because the driver didn't + // exist ... this should return + // a real error, like an exception! + timestamp = systemTime(SYSTEM_TIME_MONOTONIC); + checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, + METHOD_SYSTEMTIME); + return timestamp; #else - int64_t when = systemTime(SYSTEM_TIME_MONOTONIC); - return (int64_t) nanoseconds_to_milliseconds(when); + return systemTime(SYSTEM_TIME_MONOTONIC); #endif } diff --git a/libs/utils/Timers.cpp b/libs/utils/Timers.cpp index 64b4701..d4f8516 100644 --- a/libs/utils/Timers.cpp +++ b/libs/utils/Timers.cpp @@ -39,7 +39,8 @@ nsecs_t systemTime(int clock) CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID, - CLOCK_THREAD_CPUTIME_ID + CLOCK_THREAD_CPUTIME_ID, + CLOCK_BOOTTIME }; struct timespec t; t.tv_sec = t.tv_nsec = 0; diff --git a/libs/utils/Trace.cpp b/libs/utils/Trace.cpp index 5cd5731..f5aaea3 100644 --- a/libs/utils/Trace.cpp +++ b/libs/utils/Trace.cpp @@ -25,7 +25,7 @@ namespace android { volatile int32_t Tracer::sIsReady = 0; int Tracer::sTraceFD = -1; -uint64_t Tracer::sEnabledTags = 0; +uint64_t Tracer::sEnabledTags = ATRACE_TAG_NOT_READY; Mutex Tracer::sMutex; void Tracer::changeCallback() { @@ -46,7 +46,7 @@ void Tracer::init() { sTraceFD = open(traceFileName, O_WRONLY); if (sTraceFD == -1) { ALOGE("error opening trace file: %s (%d)", strerror(errno), errno); - // sEnabledTags remains zero indicating that no tracing can occur + sEnabledTags = 0; // no tracing can occur } else { loadSystemProperty(); } diff --git a/libs/utils/VectorImpl.cpp b/libs/utils/VectorImpl.cpp index e78faa8..c3257bb 100644 --- a/libs/utils/VectorImpl.cpp +++ b/libs/utils/VectorImpl.cpp @@ -20,7 +20,8 @@ #include <stdlib.h> #include <stdio.h> -#include <utils/Log.h> +#include <cutils/log.h> + #include <utils/Errors.h> #include <utils/SharedBuffer.h> #include <utils/VectorImpl.h> @@ -50,15 +51,14 @@ VectorImpl::VectorImpl(const VectorImpl& rhs) mFlags(rhs.mFlags), mItemSize(rhs.mItemSize) { if (mStorage) { - SharedBuffer::sharedBuffer(mStorage)->acquire(); + SharedBuffer::bufferFromData(mStorage)->acquire(); } } VectorImpl::~VectorImpl() { - ALOG_ASSERT(!mCount, - "[%p] " - "subclasses of VectorImpl must call finish_vector()" + ALOGW_IF(mCount, + "[%p] subclasses of VectorImpl must call finish_vector()" " in their destructor. Leaking %d bytes.", this, (int)(mCount*mItemSize)); // We can't call _do_destroy() here because the vtable is already gone. @@ -66,14 +66,14 @@ VectorImpl::~VectorImpl() VectorImpl& VectorImpl::operator = (const VectorImpl& rhs) { - ALOG_ASSERT(mItemSize == rhs.mItemSize, + LOG_ALWAYS_FATAL_IF(mItemSize != rhs.mItemSize, "Vector<> have different types (this=%p, rhs=%p)", this, &rhs); if (this != &rhs) { release_storage(); if (rhs.mCount) { mStorage = rhs.mStorage; mCount = rhs.mCount; - SharedBuffer::sharedBuffer(mStorage)->acquire(); + SharedBuffer::bufferFromData(mStorage)->acquire(); } else { mStorage = 0; mCount = 0; @@ -85,7 +85,7 @@ VectorImpl& VectorImpl::operator = (const VectorImpl& rhs) void* VectorImpl::editArrayImpl() { if (mStorage) { - SharedBuffer* sb = SharedBuffer::sharedBuffer(mStorage)->attemptEdit(); + SharedBuffer* sb = SharedBuffer::bufferFromData(mStorage)->attemptEdit(); if (sb == 0) { sb = SharedBuffer::alloc(capacity() * mItemSize); if (sb) { @@ -101,7 +101,7 @@ void* VectorImpl::editArrayImpl() size_t VectorImpl::capacity() const { if (mStorage) { - return SharedBuffer::sharedBuffer(mStorage)->size() / mItemSize; + return SharedBuffer::bufferFromData(mStorage)->size() / mItemSize; } return 0; } @@ -251,6 +251,10 @@ ssize_t VectorImpl::replaceAt(const void* prototype, size_t index) ALOG_ASSERT(index<size(), "[%p] replace: index=%d, size=%d", this, (int)index, (int)size()); + if (index >= size()) { + return BAD_INDEX; + } + void* item = editItemLocation(index); if (item != prototype) { if (item == 0) @@ -294,10 +298,13 @@ void* VectorImpl::editItemLocation(size_t index) ALOG_ASSERT(index<capacity(), "[%p] editItemLocation: index=%d, capacity=%d, count=%d", this, (int)index, (int)capacity(), (int)mCount); - - void* buffer = editArrayImpl(); - if (buffer) - return reinterpret_cast<char*>(buffer) + index*mItemSize; + + if (index < capacity()) { + void* buffer = editArrayImpl(); + if (buffer) { + return reinterpret_cast<char*>(buffer) + index*mItemSize; + } + } return 0; } @@ -307,9 +314,12 @@ const void* VectorImpl::itemLocation(size_t index) const "[%p] itemLocation: index=%d, capacity=%d, count=%d", this, (int)index, (int)capacity(), (int)mCount); - const void* buffer = arrayImpl(); - if (buffer) - return reinterpret_cast<const char*>(buffer) + index*mItemSize; + if (index < capacity()) { + const void* buffer = arrayImpl(); + if (buffer) { + return reinterpret_cast<const char*>(buffer) + index*mItemSize; + } + } return 0; } @@ -336,7 +346,7 @@ ssize_t VectorImpl::setCapacity(size_t new_capacity) void VectorImpl::release_storage() { if (mStorage) { - const SharedBuffer* sb = SharedBuffer::sharedBuffer(mStorage); + const SharedBuffer* sb = SharedBuffer::bufferFromData(mStorage); if (sb->release(SharedBuffer::eKeepStorage) == 1) { _do_destroy(mStorage, mCount); SharedBuffer::dealloc(sb); @@ -362,7 +372,7 @@ void* VectorImpl::_grow(size_t where, size_t amount) (mFlags & HAS_TRIVIAL_COPY) && (mFlags & HAS_TRIVIAL_DTOR)) { - const SharedBuffer* cur_sb = SharedBuffer::sharedBuffer(mStorage); + const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage); SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize); mStorage = sb->data(); } else { @@ -414,7 +424,7 @@ void VectorImpl::_shrink(size_t where, size_t amount) (mFlags & HAS_TRIVIAL_COPY) && (mFlags & HAS_TRIVIAL_DTOR)) { - const SharedBuffer* cur_sb = SharedBuffer::sharedBuffer(mStorage); + const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage); SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize); mStorage = sb->data(); } else { diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp index cad7720..a1bfedb 100644 --- a/libs/utils/ZipFileRO.cpp +++ b/libs/utils/ZipFileRO.cpp @@ -20,6 +20,7 @@ #define LOG_TAG "zipro" //#define LOG_NDEBUG 0 #include <utils/Log.h> +#include <utils/Compat.h> #include <utils/ZipFileRO.h> #include <utils/misc.h> #include <utils/threads.h> @@ -32,14 +33,6 @@ #include <assert.h> #include <unistd.h> -#if HAVE_PRINTF_ZD -# define ZD "%zd" -# define ZD_TYPE ssize_t -#else -# define ZD "%ld" -# define ZD_TYPE long -#endif - /* * We must open binary files using open(path, ... | O_BINARY) under Windows. * Otherwise strange read errors will happen. @@ -48,21 +41,6 @@ # define O_BINARY 0 #endif -/* - * TEMP_FAILURE_RETRY is defined by some, but not all, versions of - * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's - * not already defined, then define it here. - */ -#ifndef TEMP_FAILURE_RETRY -/* Used to retry syscalls that can return EINTR. */ -#define TEMP_FAILURE_RETRY(exp) ({ \ - typeof (exp) _rc; \ - do { \ - _rc = (exp); \ - } while (_rc == -1 && errno == EINTR); \ - _rc; }) -#endif - using namespace android; /* @@ -118,7 +96,7 @@ ZipFileRO::~ZipFileRO() { */ int ZipFileRO::entryToIndex(const ZipEntryRO entry) const { - long ent = ((long) entry) - kZipEntryAdj; + long ent = ((intptr_t) entry) - kZipEntryAdj; if (ent < 0 || ent >= mHashTableSize || mHashTable[ent].name == NULL) { ALOGW("Invalid ZipEntryRO %p (%ld)\n", entry, ent); return -1; @@ -140,7 +118,7 @@ status_t ZipFileRO::open(const char* zipFileName) /* * Open and map the specified file. */ - fd = ::open(zipFileName, O_RDONLY | O_BINARY); + fd = TEMP_FAILURE_RETRY(::open(zipFileName, O_RDONLY | O_BINARY)); if (fd < 0) { ALOGW("Unable to open zip '%s': %s\n", zipFileName, strerror(errno)); return NAME_NOT_FOUND; @@ -320,6 +298,25 @@ bool ZipFileRO::mapCentralDirectory(void) return true; } + +/* + * Round up to the next highest power of 2. + * + * Found on http://graphics.stanford.edu/~seander/bithacks.html. + */ +static unsigned int roundUpPower2(unsigned int val) +{ + val--; + val |= val >> 1; + val |= val >> 2; + val |= val >> 4; + val |= val >> 8; + val |= val >> 16; + val++; + + return val; +} + bool ZipFileRO::parseZipArchive(void) { bool result = false; @@ -459,7 +456,7 @@ ZipEntryRO ZipFileRO::findEntryByIndex(int idx) const for (int ent = 0; ent < mHashTableSize; ent++) { if (mHashTable[ent].name != NULL) { if (idx-- == 0) - return (ZipEntryRO) (ent + kZipEntryAdj); + return (ZipEntryRO) (intptr_t)(ent + kZipEntryAdj); } } @@ -752,7 +749,7 @@ bool ZipFileRO::uncompressEntry(ZipEntryRO entry, int fd) const ptr = (const unsigned char*) file->getDataPtr(); if (method == kCompressStored) { - ssize_t actual = write(fd, ptr, uncompLen); + ssize_t actual = TEMP_FAILURE_RETRY(write(fd, ptr, uncompLen)); if (actual < 0) { ALOGE("Write failed: %s\n", strerror(errno)); goto unmap; @@ -901,9 +898,12 @@ bail: (zerr == Z_STREAM_END && zstream.avail_out != sizeof(writeBuf))) { long writeSize = zstream.next_out - writeBuf; - int cc = write(fd, writeBuf, writeSize); - if (cc != (int) writeSize) { - ALOGW("write failed in inflate (%d vs %ld)\n", cc, writeSize); + int cc = TEMP_FAILURE_RETRY(write(fd, writeBuf, writeSize)); + if (cc < 0) { + ALOGW("write failed in inflate: %s", strerror(errno)); + goto z_bail; + } else if (cc != (int) writeSize) { + ALOGW("write failed in inflate (%d vs %ld)", cc, writeSize); goto z_bail; } diff --git a/libs/utils/ZipUtils.cpp b/libs/utils/ZipUtils.cpp index cf5467b..a43bbb0 100644 --- a/libs/utils/ZipUtils.cpp +++ b/libs/utils/ZipUtils.cpp @@ -21,6 +21,7 @@ #define LOG_TAG "ziputil" #include <utils/Log.h> +#include <utils/Compat.h> #include <utils/ZipUtils.h> #include <utils/ZipFileRO.h> @@ -98,10 +99,11 @@ using namespace android; ALOGV("+++ reading %ld bytes (%ld left)\n", getSize, compRemaining); - int cc = read(fd, readBuf, getSize); - if (cc != (int) getSize) { - ALOGD("inflate read failed (%d vs %ld)\n", - cc, getSize); + int cc = TEMP_FAILURE_RETRY(read(fd, readBuf, getSize)); + if (cc < 0) { + ALOGW("inflate read failed: %s", strerror(errno)); + } else if (cc != (int) getSize) { + ALOGW("inflate read failed (%d vs %ld)", cc, getSize); goto z_bail; } diff --git a/libs/utils/misc.cpp b/libs/utils/misc.cpp index b3c99e6..445a23a 100644 --- a/libs/utils/misc.cpp +++ b/libs/utils/misc.cpp @@ -39,90 +39,6 @@ using namespace android; namespace android { /* - * Like strdup(), but uses C++ "new" operator instead of malloc. - */ -char* strdupNew(const char* str) -{ - char* newStr; - int len; - - if (str == NULL) - return NULL; - - len = strlen(str); - newStr = new char[len+1]; - memcpy(newStr, str, len+1); - - return newStr; -} - -/* - * Concatenate an argument vector. - */ -char* concatArgv(int argc, const char* const argv[]) -{ - char* newStr = NULL; - int len, totalLen, posn, idx; - - /* - * First, figure out the total length. - */ - totalLen = idx = 0; - while (1) { - if (idx == argc || argv[idx] == NULL) - break; - if (idx) - totalLen++; // leave a space between args - totalLen += strlen(argv[idx]); - idx++; - } - - /* - * Alloc the string. - */ - newStr = new char[totalLen +1]; - if (newStr == NULL) - return NULL; - - /* - * Finally, allocate the string and copy data over. - */ - idx = posn = 0; - while (1) { - if (idx == argc || argv[idx] == NULL) - break; - if (idx) - newStr[posn++] = ' '; - - len = strlen(argv[idx]); - memcpy(&newStr[posn], argv[idx], len); - posn += len; - - idx++; - } - - assert(posn == totalLen); - newStr[posn] = '\0'; - - return newStr; -} - -/* - * Count the #of args in an argument vector. Don't count the final NULL. - */ -int countArgv(const char* const argv[]) -{ - int count = 0; - - while (argv[count] != NULL) - count++; - - return count; -} - - -#include <stdio.h> -/* * Get a file's type. */ FileType getFileType(const char* fileName) @@ -172,24 +88,6 @@ time_t getFileModDate(const char* fileName) return sb.st_mtime; } -/* - * Round up to the next highest power of 2. - * - * Found on http://graphics.stanford.edu/~seander/bithacks.html. - */ -unsigned int roundUpPower2(unsigned int val) -{ - val--; - val |= val >> 1; - val |= val >> 2; - val |= val >> 4; - val |= val >> 8; - val |= val >> 16; - val++; - - return val; -} - struct sysprop_change_callback_info { sysprop_change_callback callback; int priority; diff --git a/libs/utils/tests/Android.mk b/libs/utils/tests/Android.mk index 0a5b379..5b2b5b1 100644 --- a/libs/utils/tests/Android.mk +++ b/libs/utils/tests/Android.mk @@ -4,42 +4,30 @@ include $(CLEAR_VARS) # Build the unit tests. test_src_files := \ - BasicHashtable_test.cpp \ - BlobCache_test.cpp \ - Looper_test.cpp \ - String8_test.cpp \ - Unicode_test.cpp \ - Vector_test.cpp \ - ZipFileRO_test.cpp + BasicHashtable_test.cpp \ + BlobCache_test.cpp \ + Looper_test.cpp \ + String8_test.cpp \ + Unicode_test.cpp \ + Vector_test.cpp \ + ZipFileRO_test.cpp shared_libraries := \ - libz \ - liblog \ - libcutils \ - libutils \ - libstlport + libz \ + liblog \ + libcutils \ + libutils \ + libstlport static_libraries := \ - libgtest \ - libgtest_main - -c_includes := \ - external/zlib \ - external/icu4c/common \ - bionic \ - bionic/libstdc++/include \ - external/gtest/include \ - external/stlport/stlport - -module_tags := eng tests + libgtest \ + libgtest_main $(foreach file,$(test_src_files), \ $(eval include $(CLEAR_VARS)) \ $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \ $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \ - $(eval LOCAL_C_INCLUDES := $(c_includes)) \ $(eval LOCAL_SRC_FILES := $(file)) \ $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \ - $(eval LOCAL_MODULE_TAGS := $(module_tags)) \ - $(eval include $(BUILD_EXECUTABLE)) \ + $(eval include $(BUILD_NATIVE_TEST)) \ ) |