// The default to use if no other ignore pattern is defined.
const char * const gDefaultIgnoreAssets =
- "!.svn:!.git:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*.scc:*~";
+ "!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~";
// The ignore pattern that can be passed via --ignore-assets in Main.cpp
const char * gUserIgnoreAssets = NULL;
LOCAL_CFLAGS += -Wno-format-y2k
+ifeq (darwin,$(HOST_OS))
+LOCAL_CFLAGS += -D_DARWIN_UNLIMITED_STREAMS
+endif
+
-LOCAL_C_INCLUDES += external/expat/lib
LOCAL_C_INCLUDES += external/libpng
LOCAL_C_INCLUDES += external/zlib
LOCAL_C_INCLUDES += build/libs/host/include
mUpdate(false), mExtending(false),
mRequireLocalization(false), mPseudolocalize(false),
mWantUTF16(false), mValues(false),
- mCompressionMethod(0), mOutputAPKFile(NULL),
+ mCompressionMethod(0), mJunkPath(false), mOutputAPKFile(NULL),
mManifestPackageNameOverride(NULL), mInstrumentationPackageNameOverride(NULL),
- mIsOverlayPackage(false),
mAutoAddOverlay(false), mGenDependencies(false),
mAssetSourceDir(NULL),
mCrunchedOutputDir(NULL), mProguardFile(NULL),
mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL),
mVersionCode(NULL), mVersionName(NULL), mCustomPackage(NULL), mExtraPackages(NULL),
mMaxResVersion(NULL), mDebugMode(false), mNonConstantId(false), mProduct(NULL),
- mUseCrunchCache(false), mOutputTextSymbols(NULL),
+ mUseCrunchCache(false), mErrorOnFailedInsert(false), mOutputTextSymbols(NULL),
mArgc(0), mArgv(NULL)
{}
~Bundle(void) {}
void setManifestPackageNameOverride(const char * val) { mManifestPackageNameOverride = val; }
const char* getInstrumentationPackageNameOverride() const { return mInstrumentationPackageNameOverride; }
void setInstrumentationPackageNameOverride(const char * val) { mInstrumentationPackageNameOverride = val; }
- bool getIsOverlayPackage() const { return mIsOverlayPackage; }
- void setIsOverlayPackage(bool val) { mIsOverlayPackage = val; }
bool getAutoAddOverlay() { return mAutoAddOverlay; }
void setAutoAddOverlay(bool val) { mAutoAddOverlay = val; }
bool getGenDependencies() { return mGenDependencies; }
void setGenDependencies(bool val) { mGenDependencies = val; }
+ bool getErrorOnFailedInsert() { return mErrorOnFailedInsert; }
+ void setErrorOnFailedInsert(bool val) { mErrorOnFailedInsert = val; }
bool getUTF16StringsOption() {
return mWantUTF16 || !isMinSdkAtLeast(SDK_FROYO);
const char* mOutputAPKFile;
const char* mManifestPackageNameOverride;
const char* mInstrumentationPackageNameOverride;
- bool mIsOverlayPackage;
bool mAutoAddOverlay;
bool mGenDependencies;
const char* mAssetSourceDir;
bool mNonConstantId;
const char* mProduct;
bool mUseCrunchCache;
+ bool mErrorOnFailedInsert;
const char* mOutputTextSymbols;
/* file specification */
" [-F apk-file] [-J R-file-dir] \\\n"
" [--product product1,product2,...] \\\n"
" [-c CONFIGS] [--preferred-configurations CONFIGS] \\\n"
- " [-o] \\\n"
" [raw-files-dir [raw-files-dir] ...] \\\n"
" [--output-text-symbols DIR]\n"
"\n"
" -j specify a jar or zip file containing classes to include\n"
" -k junk path of file(s) added\n"
" -m make package directories under location specified by -J\n"
- " -o create overlay package (ie only resources; expects <overlay-package> in manifest)\n"
#if 0
" -p pseudolocalize the default configuration\n"
#endif
" Make the resources ID non constant. This is required to make an R java class\n"
" that does not contain the final value but is used to make reusable compiled\n"
" libraries that need to access resources.\n"
+ " --error-on-failed-insert\n"
+ " Forces aapt to return an error if it fails to insert values into the manifest\n"
+ " with --debug-mode, --min-sdk-version, --target-sdk-version --version-code\n"
+ " and --version-name.\n"
+ " Insertion typically fails if the manifest already defines the attribute.\n"
" --output-text-symbols\n"
" Generates a text file containing the resource symbols of the R class in the\n"
" specified folder.\n"
case 'm':
bundle.setMakePackageDirs(true);
break;
- case 'o':
- bundle.setIsOverlayPackage(true);
- break;
#if 0
case 'p':
bundle.setPseudolocalize(true);
bundle.setInstrumentationPackageNameOverride(argv[0]);
} else if (strcmp(cp, "-auto-add-overlay") == 0) {
bundle.setAutoAddOverlay(true);
+ } else if (strcmp(cp, "-error-on-failed-insert") == 0) {
+ bundle.setErrorOnFailedInsert(true);
} else if (strcmp(cp, "-output-text-symbols") == 0) {
argc--;
argv++;
return true;
}
-void addTagAttribute(const sp<XMLNode>& node, const char* ns8,
- const char* attr8, const char* value)
+/*
+ * Inserts an attribute in a given node, only if the attribute does not
+ * exist.
+ * If errorOnFailedInsert is true, and the attribute already exists, returns false.
+ * Returns true otherwise, even if the attribute already exists.
+ */
+bool addTagAttribute(const sp<XMLNode>& node, const char* ns8,
+ const char* attr8, const char* value, bool errorOnFailedInsert)
{
if (value == NULL) {
- return;
+ return true;
}
-
+
const String16 ns(ns8);
const String16 attr(attr8);
-
+
if (node->getAttribute(ns, attr) != NULL) {
+ if (errorOnFailedInsert) {
+ fprintf(stderr, "Error: AndroidManifest.xml already defines %s (in %s);"
+ " cannot insert new value %s.\n",
+ String8(attr).string(), String8(ns).string(), value);
+ return false;
+ }
+
fprintf(stderr, "Warning: AndroidManifest.xml already defines %s (in %s);"
" using existing value in manifest.\n",
String8(attr).string(), String8(ns).string());
- return;
+
+ // don't stop the build.
+ return true;
}
node->addAttribute(ns, attr, String16(value));
+ return true;
}
static void fullyQualifyClassName(const String8& package, sp<XMLNode> node,
fprintf(stderr, "No <manifest> tag.\n");
return UNKNOWN_ERROR;
}
-
- addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionCode",
- bundle->getVersionCode());
- addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionName",
- bundle->getVersionName());
+
+ bool errorOnFailedInsert = bundle->getErrorOnFailedInsert();
+
+ if (!addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionCode",
+ bundle->getVersionCode(), errorOnFailedInsert)) {
+ return UNKNOWN_ERROR;
+ }
+ if (!addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionName",
+ bundle->getVersionName(), errorOnFailedInsert)) {
+ return UNKNOWN_ERROR;
+ }
if (bundle->getMinSdkVersion() != NULL
|| bundle->getTargetSdkVersion() != NULL
root->insertChildAt(vers, 0);
}
- addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "minSdkVersion",
- bundle->getMinSdkVersion());
- addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "targetSdkVersion",
- bundle->getTargetSdkVersion());
- addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "maxSdkVersion",
- bundle->getMaxSdkVersion());
+ if (!addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "minSdkVersion",
+ bundle->getMinSdkVersion(), errorOnFailedInsert)) {
+ return UNKNOWN_ERROR;
+ }
+ if (!addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "targetSdkVersion",
+ bundle->getTargetSdkVersion(), errorOnFailedInsert)) {
+ return UNKNOWN_ERROR;
+ }
+ if (!addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "maxSdkVersion",
+ bundle->getMaxSdkVersion(), errorOnFailedInsert)) {
+ return UNKNOWN_ERROR;
+ }
}
if (bundle->getDebugMode()) {
sp<XMLNode> application = root->getChildElement(String16(), String16("application"));
if (application != NULL) {
- addTagAttribute(application, RESOURCES_ANDROID_NAMESPACE, "debuggable", "true");
+ if (!addTagAttribute(application, RESOURCES_ANDROID_NAMESPACE, "debuggable", "true",
+ errorOnFailedInsert)) {
+ return UNKNOWN_ERROR;
+ }
}
}
const bool filterable = (typeName != mipmap16);
const size_t N = t != NULL ? t->getOrderedConfigs().size() : 0;
+
+ // Until a non-NO_ENTRY value has been written for a resource,
+ // that resource is invalid; validResources[i] represents
+ // the item at t->getOrderedConfigs().itemAt(i).
+ Vector<bool> validResources;
+ validResources.insertAt(false, 0, N);
// First write the typeSpec chunk, containing information about
// each resource entry in this type.
if (amt < 0) {
return amt;
}
+ validResources.editItemAt(ei) = true;
} else {
index[ei] = htodl(ResTable_type::NO_ENTRY);
}
(((uint8_t*)data->editData()) + typeStart);
tHeader->header.size = htodl(data->getSize()-typeStart);
}
+
+ for (size_t i = 0; i < N; ++i) {
+ if (!validResources[i]) {
+ sp<ConfigList> c = t->getOrderedConfigs().itemAt(i);
+ fprintf(stderr, "warning: no entries written for %s/%s\n",
+ String8(typeName).string(), String8(c->getName()).string());
+ }
+ }
}
// Fill in the rest of the package information.
{
sp<Package> p = mPackages.valueFor(package);
if (p == NULL) {
- if (mBundle->getIsOverlayPackage()) {
- p = new Package(package, 0x00);
- } else if (mIsAppPackage) {
+ if (mIsAppPackage) {
if (mHaveAppPackage) {
fprintf(stderr, "Adding multiple application package resources; only one is allowed.\n"
"Use -x to create extended resources.\n");
#include <ctype.h>
#include <errno.h>
-#include <expat.h>
+#include <libexpat/expat.h>
using namespace android;
namespaces.pop();
} else if (code == ResXMLTree::TEXT) {
size_t len;
- printf("%sC: \"%s\"\n", prefix.string(), String8(block->getText(&len)).string());
+ printf("%sC: \"%s\"\n", prefix.string(),
+ ResTable::normalizeForOutput(String8(block->getText(&len)).string()).string());
}
}