summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNowar Gu <nowar100@gmail.com>2011-07-07 16:00:51 +0800
committermodcarl <modcarl@gmail.com>2011-07-18 21:00:40 +0800
commitedde771d8940a6f1b00fd68bcca1486b575e6d9e (patch)
tree365607046f50eec49ac5f7da6159e74c2a024433
parentb498bb679fa8b08cc9a74f3842604ac0e18fad83 (diff)
downloadgdk-edde771d8940a6f1b00fd68bcca1486b575e6d9e.tar.gz
Hooray! We done the GDK building system.
This building system is independent on NDK. It builds what is should (bitcodes), and then transfer the control to NDK building system, doing the remaining building. This code is still ugly. Need cleanup.
-rw-r--r--build/awk/check-awk.awk40
-rw-r--r--build/awk/convert-deps-to-cygwin.awk57
-rw-r--r--build/awk/extract-debuggable.awk136
-rw-r--r--build/awk/extract-launchable.awk191
-rw-r--r--build/awk/extract-package-name.awk137
-rw-r--r--build/awk/extract-pid.awk52
-rw-r--r--build/awk/extract-platform.awk43
-rw-r--r--build/awk/gen-windows-host-path.awk149
-rw-r--r--build/awk/xml.awk327
-rw-r--r--build/core/add-application.mk171
-rw-r--r--build/core/add-platform.mk33
-rw-r--r--build/core/add-toolchain.mk72
-rw-r--r--build/core/build-all.mk67
-rw-r--r--build/core/build-binary.mk129
-rw-r--r--build/core/build-bitcode.mk31
-rw-r--r--build/core/build-local.mk116
-rw-r--r--build/core/build-module.mk34
-rw-r--r--build/core/build-modules.mk59
-rw-r--r--build/core/check-cygwin-make.mk43
-rw-r--r--build/core/clear-vars.mk28
-rw-r--r--build/core/default-application.mk23
-rw-r--r--build/core/definitions.mk1285
-rw-r--r--build/core/init.mk344
-rw-r--r--build/core/main.mk138
-rw-r--r--build/core/ndk-common.sh728
-rw-r--r--build/core/prebuilt-library.mk66
-rw-r--r--build/core/prebuilt-shared-library.mk27
-rw-r--r--build/core/prebuilt-static-library.mk27
-rw-r--r--build/core/setup-abi.mk37
-rw-r--r--build/core/setup-app.mk59
-rw-r--r--build/core/setup-imports.mk36
-rw-r--r--build/core/setup-toolchain.mk102
-rw-r--r--build/gmsl/README27
-rw-r--r--build/gmsl/__gmsl854
-rw-r--r--build/gmsl/gmsl89
-rw-r--r--build/gmsl/gmsl-tests647
-rw-r--r--build/gmsl/index.html687
-rw-r--r--platforms/android-portable/arch-llvm/usr/include/test.h0
-rw-r--r--samples/bitmap-plasma-llvm/jni/Application.mk2
-rw-r--r--samples/bitmap-plasma-llvm/res/raw/armeabi-v7a/gdb.setup2
-rwxr-xr-xsamples/bitmap-plasma-llvm/res/raw/armeabi-v7a/gdbserverbin0 -> 125208 bytes
-rw-r--r--samples/bitmap-plasma-llvm/res/raw/armeabi/gdb.setup2
-rwxr-xr-xsamples/bitmap-plasma-llvm/res/raw/armeabi/gdbserverbin0 -> 125208 bytes
-rw-r--r--samples/bitmap-plasma-llvm/res/raw/gdb.setup2
-rwxr-xr-xsamples/bitmap-plasma-llvm/res/raw/gdbserverbin0 -> 125208 bytes
-rw-r--r--toolchains/llvm/config.mk1
-rw-r--r--toolchains/llvm/setup.mk45
47 files changed, 6999 insertions, 146 deletions
diff --git a/build/awk/check-awk.awk b/build/awk/check-awk.awk
new file mode 100644
index 0000000..a3a0bc8
--- /dev/null
+++ b/build/awk/check-awk.awk
@@ -0,0 +1,40 @@
+# Copyright (C) 2010 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.
+#
+
+# This script is used to check that a given awk executable
+# implements the match() and substr() functions appropriately.
+#
+# These were introduced in nawk/gawk, but the original awk
+# does not have them.
+#
+BEGIN {
+ RSTART=0
+ RLENGTH=0
+ s1="A real world example"
+ if (! match(s1,"world")) {
+ print "Fail match"
+ } else if (RSTART != 8) {
+ print "Fail RSTART ="RSTART
+ } else if (RLENGTH != 5) {
+ print "Fail RLENGTH ="RLENGTH
+ } else {
+ s2=substr(s1,RSTART,RLENGTH)
+ if (s2 != "world") {
+ print "Fail substr="s2
+ } else {
+ print "Pass"
+ }
+ }
+}
diff --git a/build/awk/convert-deps-to-cygwin.awk b/build/awk/convert-deps-to-cygwin.awk
new file mode 100644
index 0000000..5dc3646
--- /dev/null
+++ b/build/awk/convert-deps-to-cygwin.awk
@@ -0,0 +1,57 @@
+# Copyright (C) 2010 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.
+#
+
+# This script is used to convert a dependency file generated by a cygwin-less
+# GCC compiler program into something that can be parsed into a cygwin-based
+# GNU Make program.
+#
+# More specifically, it's going to translate stuff like:
+#
+# D:/Stuff/source.o: \
+# D:/Stuff/source.h \
+# C:/NDK/sysroot/include/string.h \
+# C:/NDK/sysroot/include/malloc.h
+#
+# into
+#
+# /cygdrive/d/Stuff/source.o: \
+# /cygdrive/d/Stuff/source.h \
+# /cygdrive/c/NDK/sysroot/include/string.h \
+# /cygdrive/c/NDK/sysroot/include/malloc.h
+#
+
+BEGIN {
+ # TODO: We could determine this dynamically before calling this script
+ CYGDRIVE_PREFIX = "/cygdrive/"
+}
+
+{
+ LINE=""
+ SEP=""
+ for (nn = 1; nn <= NF; nn++) {
+ if ($nn ~ /^[A-Za-z]:/) {
+ LINE = LINE SEP CYGDRIVE_PREFIX tolower(substr($nn,1,1)) "/" substr($nn,4)
+ } else {
+ LINE = LINE SEP $nn
+ }
+ SEP=" "
+ }
+ # Any leading space on the original line should be preserved
+ MARGIN=""
+ if (match($0,"^[[:space:]]+")) {
+ MARGIN=substr($0,RSTART,RLENGTH)
+ }
+ printf("%s%s\n", MARGIN, LINE)
+}
diff --git a/build/awk/extract-debuggable.awk b/build/awk/extract-debuggable.awk
new file mode 100644
index 0000000..7aa9ec8
--- /dev/null
+++ b/build/awk/extract-debuggable.awk
@@ -0,0 +1,136 @@
+# Copyright (C) 2010 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.
+#
+# A nawk/gawk script used to extract the debuggable flag from an
+# application's manifest (i.e. AndroidManifest.xml). Usage:
+#
+# awk -f <this-script> AndroidManifest.xml
+#
+
+BEGIN {
+ DEBUGGABLE = "";
+ while ( xml_event() ) {
+ # simply extract the 'android:debuggable' attribute value from
+ # the first <manifest><application> element we find.
+ if ( XML_TYPE == "BEGIN" && XML_TAG == "APPLICATION" &&
+ XML_RPATH == "APPLICATION/MANIFEST/" ) {
+ DEBUGGABLE = XML_ATTR["android:debuggable"];
+ break;
+ }
+ }
+ # ensure the value is either "true" or "false"
+ if ( DEBUGGABLE != "true" )
+ DEBUGGABLE = "false";
+
+ print DEBUGGABLE;
+}
+
+#
+# the following is copied directly from xml.awk - see this file for
+# usage and implementation details.
+#
+function xml_event () {
+ RS=">";
+ XML_TAG=XML_TYPE="";
+ split("", XML_ATTR);
+ while ( 1 ) {
+ if (_xml_closing) { # delayed direct tag closure
+ XML_TAG = _xml_closing;
+ XML_TYPE = "END";
+ _xml_closing = "";
+ _xml_exit(XML_TAG);
+ return 1;
+ }
+ if (getline <= 0) return 0; # read new input line
+ _xml_p = index($0, "<"); # get start marker
+ if (_xml_p == 0) return 0; # end of file (or malformed input)
+ $0 = substr($0, _xml_p) # remove anything before '<'
+ # ignore CData / Comments / Processing instructions / Declarations
+ if (_xml_in_section("<!\\[[Cc][Dd][Aa][Tt][Aa]\\[", "]]") ||
+ _xml_in_section("<!--", "--") ||
+ _xml_in_section("<\\?", "\\?") ||
+ _xml_in_section("<!", "")) {
+ continue;
+ }
+ if (substr($0, 1, 2) == "</") { # is it a closing tag ?
+ XML_TYPE = "END";
+ $0 = substr($0, 3);
+ } else { # nope, it's an opening one
+ XML_TYPE = "BEGIN";
+ $0 = substr($0, 2);
+ }
+ XML_TAG = $0
+ sub("[ \n\t/].*$", "", XML_TAG); # extract tag name
+ XML_TAG = toupper(XML_TAG); # uppercase it
+ if ( XML_TAG !~ /^[A-Z][-+_.:0-9A-Z]*$/ ) # validate it
+ _xml_panic("Invalid tag name: " XML_TAG);
+ if (XML_TYPE == "BEGIN") { # update reverse path
+ _xml_enter(XML_TAG);
+ } else {
+ _xml_exit(XML_TAG);
+ }
+ sub("[^ \n\t]*[ \n\t]*", "", $0); # get rid of tag and spaces
+ while ($0) { # process attributes
+ if ($0 == "/") { # deal with direct closing tag, e.g. </foo>
+ _xml_closing = XML_TAG; # record delayed tag closure.
+ break
+ }
+ _xml_attrib = $0;
+ sub(/=.*$/,"",_xml_attrib); # extract attribute name
+ sub(/^[^=]*/,"",$0); # remove it from record
+ _xml_attrib = tolower(_xml_attrib);
+ if ( _xml_attrib !~ /^[a-z][-+_0-9a-z:]*$/ ) # validate it
+ _xml_panic("Invalid attribute name: " _xml_attrib);
+ if (substr($0,1,2) == "=\"") { # value is ="something"
+ _xml_value = substr($0,3);
+ sub(/".*$/,"",_xml_value);
+ sub(/^="[^"]*"/,"",$0);
+ } else if (substr($0,1,2) == "='") { # value is ='something'
+ _xml_value = substr($0,3);
+ sub(/'.*$/,"",_xml_value);
+ sub(/^='[^']*'/,"",$0);
+ } else {
+ _xml_panic("Invalid attribute value syntax for " _xml_attrib ": " $0);
+ }
+ XML_ATTR[_xml_attrib] = _xml_value; # store attribute name/value
+ sub(/^[ \t\n]*/,"",$0); # get rid of remaining leading spaces
+ }
+ return 1; # now return, XML_TYPE/TAG/ATTR/RPATH are set
+ }
+}
+
+function _xml_panic (msg) {
+ print msg > "/dev/stderr"
+ exit(1)
+}
+
+function _xml_in_section (sec_begin, sec_end) {
+ if (!match( $0, "^" sec_begin )) return 0;
+ while (!match($0, sec_end "$")) {
+ if (getline <= 0) _xml_panic("Unexpected EOF: " ERRNO);
+ }
+ return 1;
+}
+
+function _xml_enter (tag) {
+ XML_RPATH = tag "/" XML_RPATH;
+}
+
+function _xml_exit (tag) {
+ _xml_p = index(XML_RPATH, "/");
+ _xml_expected = substr(XML_RPATH, 1, _xml_p-1);
+ if (_xml_expected != XML_TAG)
+ _xml_panic("Unexpected close tag: " XML_TAG ", expecting " _xml_expected);
+ XML_RPATH = substr(XML_RPATH, _xml_p+1);
+}
diff --git a/build/awk/extract-launchable.awk b/build/awk/extract-launchable.awk
new file mode 100644
index 0000000..55bf97b
--- /dev/null
+++ b/build/awk/extract-launchable.awk
@@ -0,0 +1,191 @@
+# Copyright (C) 2010 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.
+#
+# A nawk/gawk script used to extract the list of launchable activities
+# from an application's manifest (i.e. AndroidManifest.xml). Usage:
+#
+# awk -f <this-script> AndroidManifest.xml
+#
+
+#
+# Explanation:
+#
+# A given application can have several activities, and each activity
+# can have several intent filters. We want to only list, in the final
+# output, the activities which have a intent-filter that contains the
+# following elements:
+#
+# <action android:name="android.intent.action.MAIN" />
+# <category android:name="android.intent.category.LAUNCHER" />
+#
+# To do this, we need hooks called when entering and exiting <activity>
+# and <intent-filter> elements.
+#
+
+BEGIN {
+ while ( xml_event() ) {
+ # concat xml event type and tag for simpler comparisons
+ event = XML_TYPE "-" XML_TAG;
+ # When entering a new <activity>, extract its name and set
+ # the 'launchable' flag to false.
+ if ( event == "BEGIN-ACTIVITY" &&
+ XML_RPATH == "ACTIVITY/APPLICATION/MANIFEST/" ) {
+ name = XML_ATTR["android:name"];
+ launchable = 0;
+ }
+ # When exiting an <activity>, check that it has a name and
+ # is launchable. If so, print its name to the output
+ else if ( event == "END-ACTIVITY" &&
+ XML_RPATH == "APPLICATION/MANIFEST/" ) {
+ if ( name && launchable ) {
+ # If the name doesn't contain any dot, we consider
+ # that it is just missing the initial one.
+ if (index(name, ".") == 0) {
+ name = "." name
+ }
+ print name;
+ }
+ }
+ # When entering an <intent-filter> inside an <activity>, clear
+ # the 'action' and 'category' variables. They are updated when
+ # we enter the corresponding elements within the intent-filter.
+ else if ( event == "BEGIN-INTENT-FILTER" &&
+ XML_RPATH == "INTENT-FILTER/ACTIVITY/APPLICATION/MANIFEST/" ) {
+ action = ""
+ category = ""
+ }
+ # When exiting an <intent-filter>, set the 'launchable' flag to true
+ # for the current activity if both 'action' and 'category' have the
+ # correct name.
+ else if ( event == "END-INTENT-FILTER" &&
+ XML_RPATH == "ACTIVITY/APPLICATION/MANIFEST/" ) {
+ if ( action == "android.intent.action.MAIN" &&
+ category == "android.intent.category.LAUNCHER" ) {
+ launchable = 1;
+ }
+ }
+ # When entering an <action> element inside an <intent-filter>, record
+ # its name.
+ else if ( event == "BEGIN-ACTION" &&
+ XML_RPATH == "ACTION/INTENT-FILTER/ACTIVITY/APPLICATION/MANIFEST/" ) {
+ action = XML_ATTR["android:name"];
+ }
+ # When entering a <category> element inside an <intent-filter>, record
+ # its name.
+ else if ( event == "BEGIN-CATEGORY" &&
+ XML_RPATH == "CATEGORY/INTENT-FILTER/ACTIVITY/APPLICATION/MANIFEST/" ) {
+ category = XML_ATTR["android:name"];
+ }
+ }
+}
+
+
+#
+# the following is copied directly from xml.awk - see this file for
+# usage and implementation details.
+#
+function xml_event () {
+ RS=">";
+ XML_TAG=XML_TYPE="";
+ split("", XML_ATTR);
+ while ( 1 ) {
+ if (_xml_closing) { # delayed direct tag closure
+ XML_TAG = _xml_closing;
+ XML_TYPE = "END";
+ _xml_closing = "";
+ _xml_exit(XML_TAG);
+ return 1;
+ }
+ if (getline <= 0) return 0; # read new input line
+ _xml_p = index($0, "<"); # get start marker
+ if (_xml_p == 0) return 0; # end of file (or malformed input)
+ $0 = substr($0, _xml_p) # remove anything before '<'
+ # ignore CData / Comments / Processing instructions / Declarations
+ if (_xml_in_section("<!\\[[Cc][Dd][Aa][Tt][Aa]\\[", "]]") ||
+ _xml_in_section("<!--", "--") ||
+ _xml_in_section("<\\?", "\\?") ||
+ _xml_in_section("<!", "")) {
+ continue;
+ }
+ if (substr($0, 1, 2) == "</") { # is it a closing tag ?
+ XML_TYPE = "END";
+ $0 = substr($0, 3);
+ } else { # nope, it's an opening one
+ XML_TYPE = "BEGIN";
+ $0 = substr($0, 2);
+ }
+ XML_TAG = $0
+ sub("[ \n\t/].*$", "", XML_TAG); # extract tag name
+ XML_TAG = toupper(XML_TAG); # uppercase it
+ if ( XML_TAG !~ /^[A-Z][-+_.:0-9A-Z]*$/ ) # validate it
+ _xml_panic("Invalid tag name: " XML_TAG);
+ if (XML_TYPE == "BEGIN") { # update reverse path
+ _xml_enter(XML_TAG);
+ } else {
+ _xml_exit(XML_TAG);
+ }
+ sub("[^ \n\t]*[ \n\t]*", "", $0); # get rid of tag and spaces
+ while ($0) { # process attributes
+ if ($0 == "/") { # deal with direct closing tag, e.g. </foo>
+ _xml_closing = XML_TAG; # record delayed tag closure.
+ break
+ }
+ _xml_attrib = $0;
+ sub(/=.*$/,"",_xml_attrib); # extract attribute name
+ sub(/^[^=]*/,"",$0); # remove it from record
+ _xml_attrib = tolower(_xml_attrib);
+ if ( _xml_attrib !~ /^[a-z][-+_0-9a-z:]*$/ ) # validate it
+ _xml_panic("Invalid attribute name: " _xml_attrib);
+ if (substr($0,1,2) == "=\"") { # value is ="something"
+ _xml_value = substr($0,3);
+ sub(/".*$/,"",_xml_value);
+ sub(/^="[^"]*"/,"",$0);
+ } else if (substr($0,1,2) == "='") { # value is ='something'
+ _xml_value = substr($0,3);
+ sub(/'.*$/,"",_xml_value);
+ sub(/^='[^']*'/,"",$0);
+ } else {
+ _xml_panic("Invalid attribute value syntax for " _xml_attrib ": " $0);
+ }
+ XML_ATTR[_xml_attrib] = _xml_value; # store attribute name/value
+ sub(/^[ \t\n]*/,"",$0); # get rid of remaining leading spaces
+ }
+ return 1; # now return, XML_TYPE/TAG/ATTR/RPATH are set
+ }
+}
+
+function _xml_panic (msg) {
+ print msg > "/dev/stderr"
+ exit(1)
+}
+
+function _xml_in_section (sec_begin, sec_end) {
+ if (!match( $0, "^" sec_begin )) return 0;
+ while (!match($0, sec_end "$")) {
+ if (getline <= 0) _xml_panic("Unexpected EOF: " ERRNO);
+ }
+ return 1;
+}
+
+function _xml_enter (tag) {
+ XML_RPATH = tag "/" XML_RPATH;
+}
+
+function _xml_exit (tag) {
+ _xml_p = index(XML_RPATH, "/");
+ _xml_expected = substr(XML_RPATH, 1, _xml_p-1);
+ if (_xml_expected != XML_TAG)
+ _xml_panic("Unexpected close tag: " XML_TAG ", expecting " _xml_expected);
+ XML_RPATH = substr(XML_RPATH, _xml_p+1);
+}
diff --git a/build/awk/extract-package-name.awk b/build/awk/extract-package-name.awk
new file mode 100644
index 0000000..eefb070
--- /dev/null
+++ b/build/awk/extract-package-name.awk
@@ -0,0 +1,137 @@
+# Copyright (C) 2010 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.
+#
+# A nawk/gawk script used to extract the package name from an application's
+# manifest (i.e. AndroidManifest.xml). Usage is:
+#
+# awk -f <this-script> AndroidManifest.xml
+#
+# The name itself is the value of the 'package' attribute in the
+# 'manifest' element.
+#
+
+BEGIN {
+ PACKAGE="";
+ while (xml_event()) {
+ # Simply extract the value of the 'name' attribute from
+ # the top-level <manifest> element.
+ if ( XML_TYPE == "BEGIN" && XML_RPATH == "MANIFEST/" ) {
+ PACKAGE = XML_ATTR["package"];
+ break;
+ }
+ }
+ if (!PACKAGE)
+ PACKAGE = "<none>";
+
+ print PACKAGE;
+}
+
+#
+# the following is copied directly from xml.awk - see this file for
+# usage and implementation details.
+#
+function xml_event () {
+ RS=">";
+ XML_TAG=XML_TYPE="";
+ split("", XML_ATTR);
+ while ( 1 ) {
+ if (_xml_closing) { # delayed direct tag closure
+ XML_TAG = _xml_closing;
+ XML_TYPE = "END";
+ _xml_closing = "";
+ _xml_exit(XML_TAG);
+ return 1;
+ }
+ if (getline <= 0) return 0; # read new input line
+ _xml_p = index($0, "<"); # get start marker
+ if (_xml_p == 0) return 0; # end of file (or malformed input)
+ $0 = substr($0, _xml_p) # remove anything before '<'
+ # ignore CData / Comments / Processing instructions / Declarations
+ if (_xml_in_section("<!\\[[Cc][Dd][Aa][Tt][Aa]\\[", "]]") ||
+ _xml_in_section("<!--", "--") ||
+ _xml_in_section("<\\?", "\\?") ||
+ _xml_in_section("<!", "")) {
+ continue;
+ }
+ if (substr($0, 1, 2) == "</") { # is it a closing tag ?
+ XML_TYPE = "END";
+ $0 = substr($0, 3);
+ } else { # nope, it's an opening one
+ XML_TYPE = "BEGIN";
+ $0 = substr($0, 2);
+ }
+ XML_TAG = $0
+ sub("[ \n\t/].*$", "", XML_TAG); # extract tag name
+ XML_TAG = toupper(XML_TAG); # uppercase it
+ if ( XML_TAG !~ /^[A-Z][-+_.:0-9A-Z]*$/ ) # validate it
+ _xml_panic("Invalid tag name: " XML_TAG);
+ if (XML_TYPE == "BEGIN") { # update reverse path
+ _xml_enter(XML_TAG);
+ } else {
+ _xml_exit(XML_TAG);
+ }
+ sub("[^ \n\t]*[ \n\t]*", "", $0); # get rid of tag and spaces
+ while ($0) { # process attributes
+ if ($0 == "/") { # deal with direct closing tag, e.g. </foo>
+ _xml_closing = XML_TAG; # record delayed tag closure.
+ break
+ }
+ _xml_attrib = $0;
+ sub(/=.*$/,"",_xml_attrib); # extract attribute name
+ sub(/^[^=]*/,"",$0); # remove it from record
+ _xml_attrib = tolower(_xml_attrib);
+ if ( _xml_attrib !~ /^[a-z][-+_0-9a-z:]*$/ ) # validate it
+ _xml_panic("Invalid attribute name: " _xml_attrib);
+ if (substr($0,1,2) == "=\"") { # value is ="something"
+ _xml_value = substr($0,3);
+ sub(/".*$/,"",_xml_value);
+ sub(/^="[^"]*"/,"",$0);
+ } else if (substr($0,1,2) == "='") { # value is ='something'
+ _xml_value = substr($0,3);
+ sub(/'.*$/,"",_xml_value);
+ sub(/^='[^']*'/,"",$0);
+ } else {
+ _xml_panic("Invalid attribute value syntax for " _xml_attrib ": " $0);
+ }
+ XML_ATTR[_xml_attrib] = _xml_value; # store attribute name/value
+ sub(/^[ \t\n]*/,"",$0); # get rid of remaining leading spaces
+ }
+ return 1; # now return, XML_TYPE/TAG/ATTR/RPATH are set
+ }
+}
+
+function _xml_panic (msg) {
+ print msg > "/dev/stderr"
+ exit(1)
+}
+
+function _xml_in_section (sec_begin, sec_end) {
+ if (!match( $0, "^" sec_begin )) return 0;
+ while (!match($0, sec_end "$")) {
+ if (getline <= 0) _xml_panic("Unexpected EOF: " ERRNO);
+ }
+ return 1;
+}
+
+function _xml_enter (tag) {
+ XML_RPATH = tag "/" XML_RPATH;
+}
+
+function _xml_exit (tag) {
+ _xml_p = index(XML_RPATH, "/");
+ _xml_expected = substr(XML_RPATH, 1, _xml_p-1);
+ if (_xml_expected != XML_TAG)
+ _xml_panic("Unexpected close tag: " XML_TAG ", expecting " _xml_expected);
+ XML_RPATH = substr(XML_RPATH, _xml_p+1);
+}
diff --git a/build/awk/extract-pid.awk b/build/awk/extract-pid.awk
new file mode 100644
index 0000000..9a5677c
--- /dev/null
+++ b/build/awk/extract-pid.awk
@@ -0,0 +1,52 @@
+# Copyright (C) 2010 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.
+#
+
+# Extract the pid of a given package name. This assumes that the
+# input is the product of 'adb shell ps' and that the PACKAGE variable
+# has been initialized to the package's name. In other words, this should
+# be used as:
+#
+# adb shell ps | awk -f <this-script> -v PACKAGE=<name>
+#
+# The printed value will be 0 if the package is not found.
+#
+# NOTE: For some reason, simply using $9 == PACKAGE does not work
+# with this script, so use pattern matching instead.
+#
+
+BEGIN {
+ PID=0
+ FS=" "
+ # Need to escape the dots in the package name
+ #
+ # The first argument is the regular expression '\.'
+ # corresponding to a single dot character. The second
+ # argument is the replacement string, which will be '\.'
+ # for every input dot. Finally, we need to escape each
+ # backslash in the Awk strings.
+ #
+ gsub("\\.","\\.",PACKAGE)
+}
+
+# We use the fact that the 9th column of the 'ps' output
+# contains the package name, while the 2nd one contains the pid
+#
+$9 ~ PACKAGE {
+ PID=$2
+}
+
+END {
+ print PID
+}
diff --git a/build/awk/extract-platform.awk b/build/awk/extract-platform.awk
new file mode 100644
index 0000000..c138e1e
--- /dev/null
+++ b/build/awk/extract-platform.awk
@@ -0,0 +1,43 @@
+# Copyright (C) 2009 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.
+#
+# A nawk/gawk script used to extract the application's platform name from
+# its default.properties file. It is called from build/core/add-application.mk
+#
+
+# we look for a line that looks like one of:
+# target=android-<api>
+# target=<vendor>:<name>:<api>
+#
+# <api> is a number, but can also be "Donut" for the first form,
+# as a special case.
+#
+BEGIN {
+ android_regex="android-[0-9A-Za-z_-]+"
+ vendor_regex=":[0-9]+\\s*$"
+ API=unknown
+}
+
+/^target\s*=\s*.*/ {
+ if (match($0,android_regex)) {
+ API=substr($0,RSTART,RLENGTH)
+ }
+ else if (match($0,vendor_regex)) {
+ API="android-" substr($0,RSTART+1,RLENGTH)
+ }
+}
+
+END {
+ printf("%s", API)
+}
diff --git a/build/awk/gen-windows-host-path.awk b/build/awk/gen-windows-host-path.awk
new file mode 100644
index 0000000..b72f4b7
--- /dev/null
+++ b/build/awk/gen-windows-host-path.awk
@@ -0,0 +1,149 @@
+# Copyright (C) 2010 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.
+#
+
+# This script is used to generate a Makefile fragment that will be evaluated
+# at runtime by the NDK build system during its initialization pass.
+#
+# The purpose of this generated fragment is to define a function, named
+# 'cygwin-to-host-path' that will transform a Cygwin-specific path into the
+# corresponding Windows specific one, i.e. calling
+#
+# $(call cygwin-to-host-path,/cygdrive/c/Stuff/) --> c:/Stuff
+#
+# A naive implementation of this function would be the following:
+#
+# cygwin-to-host-path = $(shell cygpath -m $1)
+#
+# Unfortunately, calling 'cygpath -m' from GNU Make is horridly slow and people
+# have complained that this was adding several minutes to their builds, even in
+# the case where there is nothing to do.
+#
+# The script expects its input to be the output of the Cygwin "mount" command
+# as in:
+#
+# C:/cygwin/bin on /usr/bin type ntfs (binary,auto)
+# C:/cygwin/lib on /usr/lib type ntfs (binary,auto)
+# C:/cygwin on / type ntfs (binary,auto)
+# C: on /cygdrive/c type ntfs (binary,posix=0,user,noumount,auto)
+# D: on /cygdrive/d type udf (binary,posix=0,user,noumount,auto)
+#
+# The script's output will be passed to the GNU Make 'eval' function
+# and will look like:
+#
+# $(patsubst /%,C:/cygwin/,
+# $(patsubst /usr/bin/%,C:/cygwin/bin/,
+# $(patsubst /usr/lib/%,C:/cygwin/lib/,
+# $(patsubst /cygdrive/C/%,C:/,
+# $(patsubst /cygdrive/D/%,D:/,
+# $(patsubst /cygdrive/c/%,C:/,
+# $(patsubst /cygdrive/d/%,D:/,$1)))))
+#
+BEGIN {
+ # setup our count
+ count = 0
+}
+
+$2 == "on" {
+ # record a new (host-path,cygwin-path) pair
+ count ++
+ host[count] = $1
+ cygwin[count] = $3
+}
+
+END {
+ # Drive letters are special cases because we must match both
+ # the upper and lower case versions to the same drive, i.e.
+ # if "mount" lists that /cygdrive/c maps to C:, we need to
+ # map both /cygdrive/c and /cygdrive/C to C: in our final rules.
+ #
+ count1 = count
+ for (nn = 1; nn <= count1; nn++) {
+ if (!match(host[nn],"^[A-Za-z]:$")) {
+ # not a driver letter mapping, skip this pair
+ continue
+ }
+ letter = substr(host[nn],1,1)
+ lo = tolower(letter)
+ up = toupper(letter)
+
+ # If the cygwin path ends in /<lo>, then substitute it with /<up>
+ # to create a new pair.
+ if (match(cygwin[nn],"/"lo"$")) {
+ count++
+ host[count] = host[nn]
+ cygwin[count] = substr(cygwin[nn],1,length(cygwin[nn])-1) up
+ continue
+ }
+
+ # If the cygwin path ends in /<up>, then substitute it with /<lo>
+ # to create a new pair.
+ if (match(cygwin[nn],"/"up"$")) {
+ count++
+ host[count] = host[nn]
+ cygwin[count] = substr(cygwin[nn],1,length(cygwin[nn])-1) lo
+ continue
+ }
+ }
+
+ # We have recorded all (host,cygwin) path pairs,
+ # now try to sort them so that the ones with the longest cygwin path
+ # appear first
+ for (ii = 2; ii <= count; ii++) {
+ for (jj = ii-1; jj > 0; jj--) {
+ if (length(cygwin[jj]) > length(cygwin[jj+1])) {
+ break;
+ }
+ if (length(cygwin[jj]) == length(cygwin[jj+1]) &&
+ cygwin[jj] > cygwin[jj+1]) {
+ break
+ }
+ tmp = cygwin[jj]
+ cygwin[jj] = cygwin[jj+1]
+ cygwin[jj+1] = tmp
+ tmp = host[jj]
+ host[jj] = host[jj+1]
+ host[jj+1] = tmp
+ }
+ }
+
+ # build/core/init.mk defines VERBOSE to 1 when it needs to dump the
+ # list of substitutions in a human-friendly format, generally when
+ # NDK_LOG is defined in the environment
+ #
+ # Otherwise, just generate the corresponding Make function definition
+ #
+ if (VERBOSE == 1) {
+ for (nn = 1; nn <= count; nn++) {
+ printf( "$(info %s => %s)", cygwin[nn], host[nn]);
+ }
+ } else {
+ RESULT = "$1"
+ for (nn = 1; nn <= count; nn++) {
+ add_drive_rule(host[nn], cygwin[nn])
+ }
+ print RESULT
+ }
+}
+
+function add_drive_rule (hostpath,cygpath)
+{
+ if (cygpath == "/") {
+ # Special case for /
+ RESULT = "$(patsubst /%," hostpath "/%,\n" RESULT ")"
+ return
+ }
+ # default rule otherwise
+ RESULT = "$(patsubst " cygpath "/%," hostpath "/%,\n" RESULT ")"
+}
diff --git a/build/awk/xml.awk b/build/awk/xml.awk
new file mode 100644
index 0000000..2cb28f5
--- /dev/null
+++ b/build/awk/xml.awk
@@ -0,0 +1,327 @@
+# Copyright (C) 2010 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.
+#
+
+# Tiny XML parser implementation in awk.
+#
+# This file is not meant to be used directly, instead copy the
+# functions it defines here into your own script then specialize
+# it appropriately.
+#
+
+# See further below for usage instructions and implementation details.
+#
+
+# ---------------------------- cut here ---------------------------
+
+function xml_event () {
+ RS=">";
+ XML_TAG=XML_TYPE="";
+ split("", XML_ATTR);
+ while ( 1 ) {
+ if (_xml_closing) { # delayed direct tag closure
+ XML_TAG = _xml_closing;
+ XML_TYPE = "END";
+ _xml_closing = "";
+ _xml_exit(XML_TAG);
+ return 1;
+ }
+ if (getline <= 0) return 0; # read new input line
+ _xml_p = index($0, "<"); # get start marker
+ if (_xml_p == 0) return 0; # end of file (or malformed input)
+ $0 = substr($0, _xml_p) # remove anything before '<'
+ # ignore CData / Comments / Processing instructions / Declarations
+ if (_xml_in_section("<!\\[[Cc][Dd][Aa][Tt][Aa]\\[", "]]") ||
+ _xml_in_section("<!--", "--") ||
+ _xml_in_section("<\\?", "\\?") ||
+ _xml_in_section("<!", "")) {
+ continue;
+ }
+ if (substr($0, 1, 2) == "</") { # is it a closing tag ?
+ XML_TYPE = "END";
+ $0 = substr($0, 3);
+ } else { # nope, it's an opening one
+ XML_TYPE = "BEGIN";
+ $0 = substr($0, 2);
+ }
+ XML_TAG = $0
+ sub("[ \n\t/].*$", "", XML_TAG); # extract tag name
+ XML_TAG = toupper(XML_TAG); # uppercase it
+ if ( XML_TAG !~ /^[A-Z][-+_.:0-9A-Z]*$/ ) # validate it
+ _xml_panic("Invalid tag name: " XML_TAG);
+ if (XML_TYPE == "BEGIN") { # update reverse path
+ _xml_enter(XML_TAG);
+ } else {
+ _xml_exit(XML_TAG);
+ }
+ sub("[^ \n\t]*[ \n\t]*", "", $0); # get rid of tag and spaces
+ while ($0) { # process attributes
+ if ($0 == "/") { # deal with direct closing tag, e.g. </foo>
+ _xml_closing = XML_TAG; # record delayed tag closure.
+ break
+ }
+ _xml_attrib = $0;
+ sub(/=.*$/,"",_xml_attrib); # extract attribute name
+ sub(/^[^=]*/,"",$0); # remove it from record
+ _xml_attrib = tolower(_xml_attrib);
+ if ( _xml_attrib !~ /^[a-z][-+_0-9a-z:]*$/ ) # validate it
+ _xml_panic("Invalid attribute name: " _xml_attrib);
+ if (substr($0,1,2) == "=\"") { # value is ="something"
+ _xml_value = substr($0,3);
+ sub(/".*$/,"",_xml_value);
+ sub(/^="[^"]*"/,"",$0);
+ } else if (substr($0,1,2) == "='") { # value is ='something'
+ _xml_value = substr($0,3);
+ sub(/'.*$/,"",_xml_value);
+ sub(/^='[^']*'/,"",$0);
+ } else {
+ _xml_panic("Invalid attribute value syntax for " _xml_attrib ": " $0);
+ }
+ XML_ATTR[_xml_attrib] = _xml_value; # store attribute name/value
+ sub(/^[ \t\n]*/,"",$0); # get rid of remaining leading spaces
+ }
+ return 1; # now return, XML_TYPE/TAG/ATTR/RPATH are set
+ }
+}
+
+function _xml_panic (msg) {
+ print msg > "/dev/stderr"
+ exit(1)
+}
+
+function _xml_in_section (sec_begin, sec_end) {
+ if (!match( $0, "^" sec_begin )) return 0;
+ while (!match($0, sec_end "$")) {
+ if (getline <= 0) _xml_panic("Unexpected EOF: " ERRNO);
+ }
+ return 1;
+}
+
+function _xml_enter (tag) {
+ XML_RPATH = tag "/" XML_RPATH;
+}
+
+function _xml_exit (tag) {
+ _xml_p = index(XML_RPATH, "/");
+ _xml_expected = substr(XML_RPATH, 1, _xml_p-1);
+ if (_xml_expected != XML_TAG)
+ _xml_panic("Unexpected close tag: " XML_TAG ", expecting " _xml_expected);
+ XML_RPATH = substr(XML_RPATH, _xml_p+1);
+}
+
+# ---------------------------- cut here ---------------------------
+
+# USAGE:
+#
+# The functions provided here are used to extract the tags and attributes of a
+# given XML file. They do not support extraction of data, CDATA, comments,
+# processing instructions and declarations at all.
+#
+# You should use this from the BEGIN {} action of your awk script (it will
+# not work from an END {} action).
+#
+# Call xml_event() in a while loop. This functions returns 1 for each XML
+# 'event' encountered, or 0 when the end of input is reached. Note that in
+# case of malformed output, an error will be printed and the script will
+# force an exit(1)
+#
+# After each succesful xml_event() call, the following variables will be set:
+#
+# XML_TYPE: type of event: "BEGIN" -> mean an opening tag, "END" a
+# closing one.
+#
+# XML_TAG: name of the tag, always in UPPERCASE!
+#
+# XML_ATTR: a map of attributes for the type. Only set for "BEGIN" types.
+# all attribute names are in lowercase.
+#
+# beware: values are *not* unescaped !
+#
+# XML_RPATH: the _reversed_ element path, using "/" as a separator.
+# if you are within the <manifest><application> tag, then
+# it will be set to "APPLICATION/MANIFEST/"
+# (note the trailing slash).
+#
+
+# This is a simple example that dumps the output of the parsing.
+#
+BEGIN {
+ while ( xml_event() ) {
+ printf "XML_TYPE=%s XML_TAG=%s XML_RPATH=%s", XML_TYPE, XML_TAG, XML_RPATH;
+ if (XML_TYPE == "BEGIN") {
+ for (attr in XML_ATTR) {
+ printf " %s='%s'", attr, XML_ATTR[attr];
+ }
+ }
+ printf "\n";
+ }
+}
+
+# IMPLEMENTATION DETAILS:
+#
+# 1. '>' as the record separator:
+#
+# RS is set to '>' to use this character as the record separator, instead of
+# the default '\n'. This means that something like the following:
+#
+# <foo><bar attrib="value">stuff</bar></foo>
+#
+# will be translated into the following successive 'records':
+#
+# <foo
+# <bar attrib="value"
+# stuff</bar
+# </foo
+#
+# Note that the '>' is never part of the records and thus will not be matched.
+# If the record does not contain a single '<', the input is either
+# malformed XML, or we reached the end of file with data after the last
+# '>'.
+#
+# Newlines in the original input are kept in the records as-is.
+#
+# 2. Getting rid of unwanted stuff:
+#
+# We don't need any of the data within elements, so we get rid of them by
+# simply ignoring anything before the '<' in the current record. This is
+# done with code like this:
+#
+# p = index($0, "<"); # get index of '<'
+# if (p == 0) -> return 0; # malformed input or end of file
+# $0 = substr($0, p+1); # remove anything before the '<' in record
+#
+# We also want to ignore certain sections like CDATA, comments, declarations,
+# etc.. These begin with a certain pattern and end with another one, e.g.
+# "<!--" and "-->" for comments. This is handled by the _xml_in_section()
+# function that accepts two patterns as input:
+#
+# sec_begin: is the pattern for the start of the record.
+# sec_end: is the pattern for the end of the record (minus trailing '>').
+#
+# The function deals with the fact that these section can embed a valid '>'
+# and will then span multiple records, i.e. something like:
+#
+# <!-- A comment with an embedded > right here ! -->
+#
+# will be decomposed into two records:
+#
+# "<!-- A comment with an embedded "
+# " right here ! --"
+#
+# The function deals with this case, and exits when such a section is not
+# properly terminated in the input.
+#
+# _xml_in_section() returns 1 if an ignorable section was found, or 0 otherwise.
+#
+# 3. Extracting the tag name:
+#
+# </foo> is a closing tag, and <foo> an opening tag, this is handled
+# by the following code:
+#
+# if (substr($0, 1, 2) == "</") {
+# XML_TYPE = "END";
+# $0 = substr($0, 3);
+# } else {
+# XML_TYPE = "BEGIN";
+# $0 = substr($0, 2);
+# }
+#
+# which defines XML_TYPE, and removes the leading "</" or "<" from the record.
+# The tag is later extracted and converted to uppercase with:
+#
+# XML_TAG = $0 # copy record
+# sub("[ \n\t/].*$", "", XML_TAG); # remove anything after tag name
+# XML_TAG = toupper(XML_TAG); # conver to uppercase
+# # validate tag
+# if ( XML_TAG !~ /^[A-Z][-+_.:0-9A-Z]*$/ ) -> panic
+#
+# Then the record is purged from the tag name and the spaces after it:
+#
+# # get rid of tag and spaces after it in $0
+# sub("[^ \n\t]*[ \n\t]*", "", $0);
+#
+# 4. Maintaining XML_RPATH:
+#
+# The _xml_enter() and _xml_exit() functions are called to maintain the
+# XML_RPATH variable when entering and exiting specific tags. _xml_exit()
+# will also validate the input, checking proper tag enclosure (or exit(1)
+# in case of error).
+#
+# if (XML_TYPE == "BEGIN") {
+# _xml_enter(XML_TAG);
+# } else {
+# _xml_exit(XML_TAG);
+# }
+#
+# 5. Extracting attributes:
+#
+# A loop is implemented to parse attributes, the idea is to get the attribute
+# name, which is always followed by a '=' character:
+#
+# _xml_attrib = $0; # copy record.
+# sub(/=.*$/,"",_xml_attrib); # get rid of '=' and anything after.
+# sub(/^[^=]*/,"",$0); # remove attribute name from $0
+# _xml_attrib = tolower(_xml_attrib);
+# if ( _xml_attrib !~ /^[a-z][-+_0-9a-z:]*$/ )
+# _xml_panic("Invalid attribute name: " _xml_attrib);
+#
+# Now get the value, which is enclosed by either (") or (')
+#
+# if (substr($0,1,2) == "=\"") { # if $0 begins with ="
+# _xml_value = substr($0,3); # extract value
+# sub(/".*$/,"",_xml_value);
+# sub(/^="[^"]*"/,"",$0); # remove it from $0
+# } else if (substr($0,1,2) == "='") { # if $0 begins with ='
+# _xml_value = substr($0,3); # extract value
+# sub(/'.*$/,"",_xml_value);
+# sub(/^='[^']*'/,"",$0); # remove it from $0
+# } else {
+# -> panic (malformed input)
+# }
+#
+# After that, we simply store the value into the XML_ATTR associative
+# array, and cleanup $0 from leading spaces:
+#
+# XML_ATTR[_xml_attrib] = _xml_value;
+# sub(/^[ \t\n]*/,"",$0);
+#
+#
+# 6. Handling direct tag closure:
+#
+# When a tag is closed directly (as in <foo/>), A single '/' will be
+# parsed in the attribute parsing loop. We need to record this for the
+# next call to xml_event(), since the current one should return a"BEGIN"
+# for the "FOO" tag instead.
+#
+# We do this by setting the special _xml_closing variable, as in:
+#
+# if ($0 == "/") {
+# # record a delayed tag closure for the next call
+# _xml_closing = XML_TAG;
+# break
+# }
+#
+# This variable is checked at the start of xml_event() like this:
+#
+# # delayed tag closure - see below
+# if (_xml_closing) {
+# XML_TAG = _xml_closing;
+# XML_TYPE = "END";
+# _xml_closing = "";
+# _xml_exit(XML_TAG);
+# return 1;
+# }
+#
+# Note the call to _xml_exit() to update XML_RPATH here.
+#
diff --git a/build/core/add-application.mk b/build/core/add-application.mk
new file mode 100644
index 0000000..6864dc6
--- /dev/null
+++ b/build/core/add-application.mk
@@ -0,0 +1,171 @@
+# Copyright (C) 2009 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.
+#
+
+# this script is used to record an application definition in the
+# GDK build system, before performing any build whatsoever.
+#
+# It is included repeatedly from build/core/main.mk and expects a
+# variable named '_application_mk' which points to a given Application.mk
+# file that will be included here. The latter must define a few variables
+# to describe the application to the build system, and the rest of the
+# code here will perform book-keeping and basic checks
+#
+
+$(call assert-defined, _application_mk _app)
+$(call gdk_log,Parsing $(_application_mk))
+
+$(call clear-vars, $(GDK_APP_VARS))
+
+# Check that GDK_DEBUG is properly defined. If it is
+# the only valid states are: undefined, 0, 1, false and true
+#
+# We set APP_DEBUG to <undefined>, 'true' or 'false'.
+#
+APP_DEBUG := $(strip $(GDK_DEBUG))
+ifeq ($(APP_DEBUG),0)
+ APP_DEBUG:= false
+endif
+ifeq ($(APP_DEBUG),1)
+ APP_DEBUG := true
+endif
+ifdef APP_DEBUG
+ ifneq (,$(filter-out true false,$(APP_DEBUG)))
+ $(call __gdk_warning,GDK_DEBUG is defined to the unsupported value '$(GDK_DEBUG)', will be ignored!)
+ endif
+endif
+
+include $(_application_mk)
+
+$(call check-required-vars,$(GDK_APP_VARS_REQUIRED),$(_application_mk))
+
+_map := GDK_APP.$(_app)
+
+# strip the 'lib' prefix in front of APP_MODULES modules
+APP_MODULES := $(call strip-lib-prefix,$(APP_MODULES))
+
+APP_PROJECT_PATH := $(strip $(APP_PROJECT_PATH))
+ifndef APP_PROJECT_PATH
+ APP_PROJECT_PATH := $(GDK_PROJECT_PATH)
+endif
+
+# check whether APP_PLATFORM is defined. If not, look for default.properties in
+# the $(APP_PROJECT_PATH) and extract the value with awk's help. If nothing is here,
+# revert to the default value (i.e. "android-3").
+#
+# NOTE: APP_PLATFORM is an experimental feature for now.
+#
+APP_PLATFORM := android-portable
+
+# If APP_BUILD_SCRIPT is defined, check that the file exists.
+# If undefined, look in $(APP_PROJECT_PATH)/jni/Android.mk
+#
+APP_BUILD_SCRIPT := $(strip $(APP_BUILD_SCRIPT))
+ifdef APP_BUILD_SCRIPT
+ _build_script := $(strip $(wildcard $(APP_BUILD_SCRIPT)))
+ ifndef _build_script
+ $(call __gdk_info,Your APP_BUILD_SCRIPT points to an unknown file: $(APP_BUILD_SCRIPT))
+ $(call __gdk_error,Aborting...)
+ endif
+ APP_BUILD_SCRIPT := $(_build_script)
+ $(call gdk_log, Using build script $(APP_BUILD_SCRIPT))
+else
+ _build_script := $(strip $(wildcard $(APP_PROJECT_PATH)/jni/Android-portable.mk))
+ ifndef _build_script
+ $(call __gdk_info,There is no Android-portable.mk under $(APP_PROJECT_PATH)/jni)
+ $(call __gdk_info,If this is intentional, please define APP_BUILD_SCRIPT to point)
+ $(call __gdk_info,to a valid GDK build script.)
+ $(call __gdk_error,Aborting...)
+ endif
+ APP_BUILD_SCRIPT := $(_build_script)
+ $(call gdk_log, Defaulted to APP_BUILD_SCRIPT=$(APP_BUILD_SCRIPT))
+endif
+
+# Determine whether the application should be debuggable.
+# - If APP_DEBUG is set to 'true', then it always should.
+# - If APP_DEBUG is set to 'false', then it never should
+# - Otherwise, extract the android:debuggable attribute from the manifest.
+#
+ifdef APP_DEBUG
+ APP_DEBUGGABLE := $(APP_DEBUG)
+ ifdef GDK_LOG
+ ifeq ($(APP_DEBUG),true)
+ $(call gdk_log,Application '$(_app)' forced debuggable through GDK_DEBUG)
+ else
+ $(call gdk_log,Application '$(_app)' forced *not* debuggable through GDK_DEBUG)
+ endif
+ endif
+else
+ # NOTE: To make unit-testing simpler, handle the case where there is no manifest.
+ APP_DEBUGGABLE := false
+ APP_MANIFEST := $(strip $(wildcard $(APP_PROJECT_PATH)/AndroidManifest.xml))
+ ifdef APP_MANIFEST
+ APP_DEBUGGABLE := $(shell $(HOST_AWK) -f $(BUILD_AWK)/extract-debuggable.awk $(APP_MANIFEST))
+ endif
+ ifdef GDK_LOG
+ ifeq ($(APP_DEBUGGABLE),true)
+ $(call gdk_log,Application '$(_app)' *is* debuggable)
+ else
+ $(call gdk_log,Application '$(_app)' is not debuggable)
+ endif
+ endif
+endif
+
+# LOCAL_BUILD_MODE will be either release or debug
+#
+# If APP_OPTIM is defined in the Application.mk, just use this.
+#
+# Otherwise, set to 'debug' if android:debuggable is set to TRUE,
+# and to 'release' if not.
+#
+ifneq ($(APP_OPTIM),)
+ # check that APP_OPTIM, if defined, is either 'release' or 'debug'
+ $(if $(filter-out release debug,$(APP_OPTIM)),\
+ $(call __gdk_info, The APP_OPTIM defined in $(_application_mk) must only be 'release' or 'debug')\
+ $(call __gdk_error,Aborting)\
+ )
+ $(call gdk_log,Selecting optimization mode through Application.mk: $(APP_OPTIM))
+else
+ ifeq ($(APP_DEBUGGABLE),true)
+ $(call gdk_log,Selecting debug optimization mode (app is debuggable))
+ APP_OPTIM := debug
+ else
+ $(call gdk_log,Selecting release optimization mode (app is not debuggable))
+ APP_OPTIM := release
+ endif
+endif
+
+# set release/debug build flags. We always use the -g flag because
+# we generate symbol versions of the binaries that are later stripped
+# when they are copied to the final project's libs/<abi> directory.
+#
+ifeq ($(APP_OPTIM),debug)
+ APP_CFLAGS := -O0 -g $(APP_CFLAGS)
+else
+ APP_CFLAGS := -O2 -DNDEBUG -g $(APP_CFLAGS)
+endif
+
+$(if $(call get,$(_map),defined),\
+ $(call __gdk_info,Weird, the application $(_app) is already defined by $(call get,$(_map),defined))\
+ $(call __gdk_error,Aborting)\
+)
+
+$(call set,$(_map),defined,$(_application_mk))
+
+# Record all app-specific variable definitions
+$(foreach __name,$(GDK_APP_VARS),\
+ $(call set,$(_map),$(__name),$($(__name)))\
+)
+
+GDK_ALL_APPS += $(_app)
diff --git a/build/core/add-platform.mk b/build/core/add-platform.mk
new file mode 100644
index 0000000..741cdc7
--- /dev/null
+++ b/build/core/add-platform.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2009 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.
+#
+
+$(call assert-defined,_platform GDK_PLATFORMS_ROOT)
+
+# For each platform, determine the corresponding supported ABIs
+# And record them in GDK_PLATFORM_$(platform)_ABIS
+#
+_abis := $(strip $(notdir $(wildcard $(GDK_PLATFORMS_ROOT)/$(_platform)/arch-*)))
+_abis := $(_abis:arch-%=%)
+
+$(call gdk_log,PLATFORM $(_platform) supports: $(_abis))
+
+GDK_PLATFORM_$(_platform)_ABIS := $(_abis)
+
+# Record the sysroots for each supported ABI
+#
+$(foreach _abi,$(_abis),\
+ $(eval GDK_PLATFORM_$(_platform)_$(_abi)_SYSROOT := $(GDK_PLATFORMS_ROOT)/$(_platform)/arch-$(_abi))\
+ $(call gdk_log, ABI $(_abi) sysroot is: $(GDK_PLATFORM_$(_platform)_$(_abi)_SYSROOT))\
+)
diff --git a/build/core/add-toolchain.mk b/build/core/add-toolchain.mk
new file mode 100644
index 0000000..8fdf2df
--- /dev/null
+++ b/build/core/add-toolchain.mk
@@ -0,0 +1,72 @@
+# Copyright (C) 2009 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.
+#
+
+# this script is included repeatedly by main.mk to add a new toolchain
+# definition to the GDK build system.
+#
+# '_config_mk' must be defined as the path of a toolchain
+# configuration file (config.mk) that will be included here.
+#
+$(call assert-defined, _config_mk)
+
+# The list of variables that must or may be defined
+# by the toolchain configuration file
+#
+GDK_TOOLCHAIN_VARS_REQUIRED := TOOLCHAIN_ABIS
+GDK_TOOLCHAIN_VARS_OPTIONAL :=
+
+# Clear variables that are supposed to be defined by the config file
+$(call clear-vars,$(GDK_TOOLCHAIN_VARS_REQUIRED))
+$(call clear-vars,$(GDK_TOOLCHAIN_VARS_OPTIONAL))
+
+# Include the config file
+include $(_config_mk)
+
+# Check that the proper variables were defined
+$(call check-required-vars,$(GDK_TOOLCHAIN_VARS_REQUIRED),$(_config_mk))
+
+# Check that the file didn't do something stupid
+$(call assert-defined, _config_mk)
+
+# Now record the toolchain-specific information
+_dir := $(patsubst %/,%,$(dir $(_config_mk)))
+_name := $(notdir $(_dir))
+_abis := $(TOOLCHAIN_ABIS)
+
+_toolchain := GDK_TOOLCHAIN.$(_name)
+
+# check that the toolchain name is unique
+$(if $(strip $($(_toolchain).defined)),\
+ $(call __gdk_error,Toolchain $(_name) defined in $(_parent) is\
+ already defined in $(GDK_TOOLCHAIN.$(_name).defined)))
+
+$(_toolchain).defined := $(_toolchain_config)
+$(_toolchain).abis := $(_abis)
+$(_toolchain).setup := $(wildcard $(_dir)/setup.mk)
+
+$(if $(strip $($(_toolchain).setup)),,\
+ $(call __gdk_error, Toolchain $(_name) lacks a setup.mk in $(_dir)))
+
+GDK_ALL_TOOLCHAINS += $(_name)
+GDK_ALL_ABIS += $(_abis)
+
+# NKD_ABI.<abi>.toolchains records the list of toolchains that support
+# a given ABI
+#
+$(foreach _abi,$(_abis),\
+ $(eval GDK_ABI.$(_abi).toolchains += $(_name)) \
+)
+
+# done
diff --git a/build/core/build-all.mk b/build/core/build-all.mk
new file mode 100644
index 0000000..c5628ad
--- /dev/null
+++ b/build/core/build-all.mk
@@ -0,0 +1,67 @@
+# Copyright (C) 2009-2010 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.
+#
+
+#
+# This script is used to build all wanted GDK binaries. It is included
+# by several scripts.
+#
+
+# ensure that the following variables are properly defined
+$(call assert-defined,GDK_APPS GDK_APP_OUT)
+
+# ====================================================================
+#
+# Prepare the build for parsing Android.mk files
+#
+# ====================================================================
+
+# These phony targets are used to control various stages of the build
+.PHONY: all \
+ installed_modules \
+ clean distclean \
+ clean-installed-binaries
+
+# These macros are used in Android.mk to include the corresponding
+# build script that will parse the LOCAL_XXX variable definitions.
+#
+CLEAR_VARS := $(BUILD_SYSTEM)/clear-vars.mk
+BUILD_BITCODE := $(BUILD_SYSTEM)/build-bitcode.mk
+
+ANDROID_MK_INCLUDED := \
+ $(CLEAR_VARS) \
+ $(BUILD_BITCODE)
+
+WANTED_INSTALLED_MODULES :=
+
+# the first rule
+all: installed_modules
+
+
+$(foreach _app,$(GDK_APPS),\
+ $(eval include $(BUILD_SYSTEM)/setup-app.mk)\
+)
+
+# ====================================================================
+#
+# Now finish the build preparation with a few rules that depend on
+# what has been effectively parsed and recorded previously
+#
+# ====================================================================
+
+clean: clean-installed-binaries
+
+distclean: clean
+
+installed_modules: clean-installed-binaries $(WANTED_INSTALLED_MODULES)
diff --git a/build/core/build-binary.mk b/build/core/build-binary.mk
new file mode 100644
index 0000000..a94d870
--- /dev/null
+++ b/build/core/build-binary.mk
@@ -0,0 +1,129 @@
+# Copyright (C) 2008 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 that LOCAL_MODULE is defined, then restore its LOCAL_XXXX values
+$(call assert-defined,LOCAL_MODULE)
+$(call module-restore-locals,$(LOCAL_MODULE))
+
+# For now, only support target (device-specific modules).
+# We may want to introduce support for host modules in the future
+# but that is too experimental for now.
+#
+my := TARGET_
+
+# LOCAL_MAKEFILE must also exist and name the Android.mk that
+# included the module build script.
+#
+$(call assert-defined,LOCAL_MAKEFILE LOCAL_BUILD_SCRIPT LOCAL_BUILT_MODULE)
+
+#
+# Ensure that 'make <module>' and 'make clean-<module>' work
+#
+.PHONY: $(LOCAL_MODULE)
+$(LOCAL_MODULE): $(LOCAL_BUILT_MODULE)
+
+cleantarget := clean-$(LOCAL_MODULE)-$(TARGET_ARCH_ABI)
+.PHONY: $(cleantarget)
+clean: $(cleantarget)
+
+$(cleantarget): PRIVATE_MODULE := $(LOCAL_MODULE)
+$(cleantarget): PRIVATE_TEXT := [$(TARGET_ARCH_ABI)]
+$(cleantarget): PRIVATE_CLEAN_FILES := $(LOCAL_BUILT_MODULE) \
+ $($(my)OBJS)
+
+$(cleantarget)::
+ @echo "Clean: $(PRIVATE_MODULE) $(PRIVATE_TEXT)"
+ $(hide) rm -rf $(PRIVATE_CLEAN_FILES)
+
+# list of generated object files
+LOCAL_OBJECTS :=
+
+#
+# always define ANDROID when building binaries
+#
+LOCAL_CFLAGS := -D__ANDROID__ -DANDROID $(LOCAL_CFLAGS)
+
+#
+# Check LOCAL_CPP_EXTENSION, use '.cpp' by default
+#
+LOCAL_CPP_EXTENSION := $(strip $(LOCAL_CPP_EXTENSION))
+ifeq ($(LOCAL_CPP_EXTENSION),)
+ LOCAL_CPP_EXTENSION := .cpp
+else
+ ifneq ($(words $(LOCAL_CPP_EXTENSION)),1)
+ $(call __gdk_info, LOCAL_CPP_EXTENSION in $(LOCAL_MAKEFILE) must be one word only, not '$(LOCAL_CPP_EXTENSION)')
+ $(call __gdk_error, Aborting)
+ endif
+endif
+
+# all_source_patterns contains the list of filename patterns that correspond
+# to source files recognized by our build system
+all_source_extensions := .c $(LOCAL_CPP_EXTENSION)
+all_source_patterns := $(foreach _ext,$(all_source_extensions),%$(_ext))
+
+unknown_sources := $(strip $(filter-out $(all_source_patterns),$(LOCAL_SRC_FILES)))
+ifdef unknown_sources
+ $(call __gdk_info,WARNING: Unsupported source file extensions in $(LOCAL_MAKEFILE) for module $(LOCAL_MODULE))
+ $(call __gdk_info, $(unknown_sources))
+endif
+
+# LOCAL_OBJECTS will list all object files corresponding to the sources
+# listed in LOCAL_SRC_FILES, in the *same* order.
+#
+LOCAL_OBJECTS := $(LOCAL_SRC_FILES)
+$(foreach _ext,$(all_source_extensions),\
+ $(eval LOCAL_OBJECTS := $$(LOCAL_OBJECTS:%$(_ext)=%.bc))\
+)
+LOCAL_OBJECTS := $(filter %.bc,$(LOCAL_OBJECTS))
+LOCAL_OBJECTS := $(foreach _obj,$(LOCAL_OBJECTS),$(LOCAL_OBJS_DIR)/$(_obj))
+
+#
+# Build the sources to object files
+#
+
+$(foreach src,$(filter %.c,$(LOCAL_SRC_FILES)), $(call compile-c-source,$(src)))
+$(foreach src,$(filter %$(LOCAL_CPP_EXTENSION),$(LOCAL_SRC_FILES)),\
+ $(call compile-cpp-source,$(src)))
+
+#
+# The compile-xxx-source calls updated LOCAL_OBJECTS and LOCAL_DEPENDENCY_DIRS
+#
+CLEAN_OBJS_DIRS += $(LOCAL_OBJS_DIR)
+
+$(LOCAL_BUILT_MODULE):
+
+$(LOCAL_BUILT_MODULE): PRIVATE_OBJECTS := $(LOCAL_OBJECTS)
+$(LOCAL_BUILT_MODULE): PRIVATE_NAME := $(notdir $(LOCAL_BUILT_MODULE))
+
+ifeq ($(call module-get-class,$(LOCAL_MODULE)),BITCODE)
+$(LOCAL_BUILT_MODULE): $(LOCAL_OBJECTS)
+ @ echo "BitcodeLibrary : $(PRIVATE_NAME)"
+ $(hide) $(cmd-link-bitcodes)
+endif
+
+#
+# If this is an installable module
+#
+ifeq ($(call module-is-installable,$(LOCAL_MODULE)),$(true))
+$(LOCAL_INSTALLED): PRIVATE_NAME := $(notdir $(LOCAL_BUILT_MODULE))
+$(LOCAL_INSTALLED): PRIVATE_SRC := $(LOCAL_BUILT_MODULE)
+$(LOCAL_INSTALLED): PRIVATE_DST_DIR := $(GDK_APP_DST_DIR)
+$(LOCAL_INSTALLED): PRIVATE_DST := $(LOCAL_INSTALLED)
+
+$(LOCAL_INSTALLED): $(LOCAL_BUILT_MODULE) clean-installed-binaries
+ @ echo "Install BCLib : $(PRIVATE_NAME) => $(call pretty-dir,$(PRIVATE_DST))"
+ $(hide) mkdir -p $(PRIVATE_DST_DIR)
+ $(hide) install -p $(PRIVATE_SRC) $(PRIVATE_DST)
+endif
diff --git a/build/core/build-bitcode.mk b/build/core/build-bitcode.mk
index c3b2137..ba3b8bd 100644
--- a/build/core/build-bitcode.mk
+++ b/build/core/build-bitcode.mk
@@ -1,22 +1,15 @@
-.PHONY: $(LOCAL_MODULE)
-ALL_BITCODE_MODULES += $(LOCAL_MODULE)
+LOCAL_BUILD_SCRIPT := BUILD_BITCODE
+LOCAL_MAKEFILE := $(local-makefile)
-# From now on, we only support these flags.
-BITCODE_MODULE.$(LOCAL_MODULE).PATH := $(LOCAL_PATH)
-BITCODE_MODULE.$(LOCAL_MODULE).SRC_FILES := $(LOCAL_SRC_FILES)
-BITCODE_MODULE.$(LOCAL_MODULE).CFLAGS := $(LOCAL_CFLAGS)
-BITCODE_MODULE.$(LOCAL_MODULE).CPPFLAGS := $(LOCAL_CFLAGS) $(LOCAL_CPPFLAGS)
+$(call check-defined-LOCAL_MODULE,$(LOCAL_BUILD_SCRIPT))
+$(call check-LOCAL_MODULE,$(LOCAL_MAKEFILE))
+$(call check-LOCAL_MODULE_FILENAME)
-$(foreach include_dir,$(LOCAL_C_INCLUDES),\
- $(eval BITCODE_MODULE.$(LOCAL_MODULE).CFLAGS += -I$(LOCAL_PATH)/$(include_dir))\
-)
-$(foreach include_dir,$(BITCODE_C_INCLUDES),\
- $(eval BITCODE_MODULE.$(LOCAL_MODULE).CFLAGS += -I$(include_dir))\
-)
+# we are building target objects
+my := TARGET_
-$(foreach include_dir,$(LOCAL_C_INCLUDES),\
- $(eval BITCODE_MODULE.$(LOCAL_MODULE).CPPFLAGS += -I$(LOCAL_PATH)/$(include_dir))\
-)
-$(foreach include_dir,$(BITCODE_C_INCLUDES),\
- $(eval BITCODE_MODULE.$(LOCAL_MODULE).CPPFLAGS += -I$(include_dir))\
-)
+$(call handle-module-filename,lib,.bc)
+$(call handle-module-built)
+
+LOCAL_MODULE_CLASS := BITCODE
+include $(BUILD_SYSTEM)/build-module.mk
diff --git a/build/core/build-local.mk b/build/core/build-local.mk
index 4ff40d6..b68eb98 100644
--- a/build/core/build-local.mk
+++ b/build/core/build-local.mk
@@ -1,45 +1,101 @@
-# TODO(Nowar): Let it more smart
-GDK_PROJECT_ROOT := $(shell pwd)
-GDK_PROJECT_OBJ := $(GDK_PROJECT_ROOT)/obj/llvm
-GDK_PROJECT_OUT := $(GDK_PROJECT_ROOT)/res/raw
-GDK_ROOT := $(GDK_PROJECT_ROOT)/../..
-
-ifeq ($(NDK_ROOT),)
- $(info Android GDK: Must figure out NDK_ROOT location.)
- $(error Aborting.)
+# Detect the GDK installation path by processing this Makefile's location.
+# This assumes we are located under $GDK_ROOT/build/core/main.mk
+#
+GDK_ROOT := $(dir $(lastword $(MAKEFILE_LIST)))
+GDK_ROOT := $(strip $(GDK_ROOT:%build/core/=%))
+GDK_ROOT := $(GDK_ROOT:%/=%)
+ifeq ($(GDK_ROOT),)
+ # for the case when we're invoked from the GDK install path
+ GDK_ROOT := .
+endif
+ifdef GDK_LOG
+ $(info Android GDK: GDK installation path auto-detected: '$(GDK_ROOT)')
+endif
+ifneq ($(words $(GDK_ROOT)),1)
+ $(info Android GDK: You GDK installation path contains spaces.)
+ $(info Android GDK: Please re-install to a different location to fix the issue !)
+ $(error Aborting.)
endif
include $(GDK_ROOT)/build/core/init.mk
-include $(GDK_TOOLCHAIN_ROOT)/setup.mk
+# ====================================================================
+#
+# If GDK_PROJECT_PATH is not defined, find the application's project
+# path by looking at the manifest file in the current directory or
+# any of its parents. If none is found, try again with 'jni/Android.mk'
+#
+# It turns out that some people use gdk-build to generate static
+# libraries without a full Android project tree.
+#
+# ====================================================================
-.PHONY: all \
- clean \
- bitcode_modules
+find-project-dir = $(strip $(call find-project-dir-inner,$1,$2))
-ALL_BITCODE_MODULES :=
+find-project-dir-inner = \
+ $(eval __found_project_path := )\
+ $(eval __find_project_path := $1)\
+ $(eval __find_project_file := $2)\
+ $(call find-project-dir-inner-2)\
+ $(__found_project_path)
--include $(GDK_PROJECT_ROOT)/jni/Android-portable.mk
+find-project-dir-inner-2 = \
+ $(call gdk_log,Looking for $(__find_project_file) in $(__find_project_path))\
+ $(eval __find_project_manifest := $(strip $(wildcard $(__find_project_path)/$(__find_project_file))))\
+ $(if $(__find_project_manifest),\
+ $(call gdk_log, Found it !)\
+ $(eval __found_project_path := $(__find_project_path))\
+ ,\
+ $(eval __find_project_parent := $(patsubst %/,%,$(dir $(__find_project_path))))\
+ $(if $(__find_project_parent),\
+ $(eval __find_project_path := $(__find_project_parent))\
+ $(call find-project-dir-inner-2)\
+ )\
+ )
-# The first rule
-all: clean bitcode_modules
+GDK_PROJECT_PATH := $(strip $(GDK_PROJECT_PATH))
+ifndef GDK_PROJECT_PATH
+ GDK_PROJECT_PATH := $(call find-project-dir,$(strip $(shell pwd)),AndroidManifest.xml)
+endif
+ifndef GDK_PROJECT_PATH
+ GDK_PROJECT_PATH := $(call find-project-dir,$(strip $(shell pwd)),jni/Android-portable.mk)
+endif
+ifndef GDK_PROJECT_PATH
+ $(call __gdk_info,Could not find application project directory !)
+ $(call __gdk_info,Please define the GDK_PROJECT_PATH variable to point to it.)
+ $(call __gdk_error,Aborting)
+endif
+
+# Check that there are no spaces in the project path, or bad things will happen
+ifneq ($(words $(GDK_PROJECT_PATH)),1)
+ $(call __gdk_info,Your Android application project path contains spaces: '$(GDK_PROJECT_PATH)')
+ $(call __gdk_info,The Android GDK build cannot work here. Please move your project to a different location.)
+ $(call __gdk_error,Aborting.)
+endif
+
+GDK_APPLICATION_MK := $(GDK_ROOT)/build/core/default-application.mk
-# TODO(Nowar): Do a real cleanup.
-clean:
-$(info rm -rf $(GDK_PROJECT_OBJ))
-$(info rm -rf $(GDK_PROJECT_OUT)/*.bc)
-$(info mkdir -p $(GDK_PROJECT_OBJ))
-$(info mkdir -p $(GDK_PROJECT_OUT))
+$(call gdk_log,Found project path: $(GDK_PROJECT_PATH))
-bitcode_modules: $(ALL_BITCODE_MODULES)
+# Place all generated files here
+GDK_APP_OUT := $(GDK_PROJECT_PATH)/obj
+
+# Fake an application named 'local'
+_app := local
+_application_mk := $(GDK_APPLICATION_MK)
+GDK_APPS := $(_app)
+
+include $(BUILD_SYSTEM)/add-application.mk
+
+# Build it
+include $(BUILD_SYSTEM)/build-all.mk
-# Now all modules are in ALL_BITCODE_MODULES
-# Take them out for each and build it
-include $(GDK_ROOT)/build/core/build-modules.mk
-# ############################################################################
#
-# Trasnfer the control to NDK
+# Transfer the control to NDK
#
-# ############################################################################
+ifndef NDK_ROOT
+ $(info Android GDK: You must specify NDK_ROOT.)
+ $(error Abort.)
+endif
include $(NDK_ROOT)/build/core/build-local.mk
diff --git a/build/core/build-module.mk b/build/core/build-module.mk
new file mode 100644
index 0000000..d0ab95d
--- /dev/null
+++ b/build/core/build-module.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2010 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.
+#
+
+$(call check-defined-LOCAL_MODULE,$(LOCAL_BUILD_SCRIPT))
+$(call check-LOCAL_MODULE,$(LOCAL_MAKEFILE))
+
+# This file is used to record the LOCAL_XXX definitions of a given
+# module. It is included by BUILD_STATIC_LIBRARY, BUILD_SHARED_LIBRARY
+# and others.
+#
+LOCAL_MODULE_CLASS := $(strip $(LOCAL_MODULE_CLASS))
+ifndef LOCAL_MODULE_CLASS
+$(call __ndk_info,$(LOCAL_MAKEFILE):$(LOCAL_MODULE): LOCAL_MODULE_CLASS definition is missing !)
+$(call __ndk_error,Aborting)
+endif
+
+$(if $(call module-class-check,$(LOCAL_MODULE_CLASS)),,\
+$(call __ndk_info,$(LOCAL_MAKEFILE):$(LOCAL_MODULE): Unknown LOCAL_MODULE_CLASS value: $(LOCAL_MODULE_CLASS))\
+$(call __ndk_error,Aborting)\
+)
+
+$(call module-add,$(LOCAL_MODULE))
diff --git a/build/core/build-modules.mk b/build/core/build-modules.mk
deleted file mode 100644
index ec8bba4..0000000
--- a/build/core/build-modules.mk
+++ /dev/null
@@ -1,59 +0,0 @@
-# TODO(Nowar): Make below rules work.
-
-#
-# $1: c source file name
-# $2: LOCAL_MODULE
-#
-define compile-c-to-bc
-$(info $(BITCODE_CC) $(BITCODE_MODULE.$(2).PATH)/$(1)\
- $(BITCODE_MODULE.$(2).CFLAGS) $(BITCODE_CFLAGS)\
- -I$(BITCODE_MODULE.$(2).PATH)\
- -c -o $(GDK_PROJECT_OBJ)/$(2)/$(1:%.c=%.bc))
-endef
-
-#
-# $1: c++ source file name
-# $2: LOCAL_MODULE
-#
-define compile-cpp-to-bc
-$(info $(BITCODE_CPP) $(BITCODE_MODULE.$(2).PATH)/$(1)\
- $(BITCODE_MODULE.$(2).CPPFLAGS) $(BITCODE_CPPFLAGS)\
- -I$(BITCODE_MODULE.$(2).PATH)\
- -c -o $(GDK_PROJECT_OBJ)/$(2)/$(1:%.cpp=%.bc))
-endef
-
-#
-# $1: source file names
-# $2: LOCAL_MODULE
-#
-define cmd-build-c-source
-$(foreach gdk_source, $(1),\
- $(call compile-c-to-bc,$(gdk_source),$(2))\
-)
-endef
-
-#
-# $1: source file names
-# $2: LOCAL_MODULE
-#
-define cmd-build-cpp-source
-$(foreach gdk_source, $(1),\
- $(call compile-cpp-to-bc,$(gdk_source),$(2))\
-)
-endef
-
-#
-# $1: bc obj files name
-# $2: LOCAL_MODULE
-#
-define cmd-link-bc
-$(info $(BITCODE_LD) $(GDK_PROJECT_OBJ)/$(2)/*.bc\
- $(BITCODE_LDFLAGS)\
- -o $(GDK_PROJECT_OUT)/lib$(2).bc)
-endef
-
-$(foreach gdk_module, $(ALL_BITCODE_MODULES),\
- $(call cmd-build-c-source,$(filter %.c,$(BITCODE_MODULE.$(gdk_module).SRC_FILES)),$(gdk_module))\
- $(call cmd-build-cpp-source,$(filter %.cpp,$(BITCODE_MODULE.$(gdk_module).SRC_FILES)),$(gdk_module))\
- $(call cmd-link-bc,$(BITCODE_MODULE.$(gdk_module).SRC_FILES),$(gdk_module))\
-)
diff --git a/build/core/check-cygwin-make.mk b/build/core/check-cygwin-make.mk
new file mode 100644
index 0000000..27bc227
--- /dev/null
+++ b/build/core/check-cygwin-make.mk
@@ -0,0 +1,43 @@
+# Copyright (C) 2010 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 that we have a Cygwin-compatible make.
+#
+# For some reason, a lot of application developers on Windows
+# have another GNU Make installed in their path, that fails
+# miserably with our build scripts. If we can detect this use
+# case, early, we will be able to dump a human-readable error
+# message with some help to fix the issue.
+#
+
+.PHONY: all
+all:
+
+# Get the cygwin-specific path to the make executable
+# (e.g. /cygdrive/c/cygwin/usr/bin/make), then strip the
+# .exe suffix, if any.
+#
+CYGWIN_MAKE := $(shell cygpath --unix --absolute $(firstword $(MAKE)))
+CYGWIN_MAKE := $(CYGWIN_MAKE:%.exe=%)
+
+# Now try to find it on the file system, a non-cygwin compatible
+# GNU Make, even if launched from a Cygwin shell, will not
+#
+SELF_MAKE := $(strip $(wildcard $(CYGWIN_MAKE).exe))
+ifeq ($(SELF_MAKE),)
+ $(error Android NDK: $(firstword $(MAKE)) is not cygwin-compatible)
+endif
+
+# that's all
diff --git a/build/core/clear-vars.mk b/build/core/clear-vars.mk
index b11d360..e3befe9 100644
--- a/build/core/clear-vars.mk
+++ b/build/core/clear-vars.mk
@@ -1,6 +1,22 @@
-# we don't want to clear LOCAL_PATH
-LOCAL_MODULE :=
-LOCAL_SRC_FILES :=
-LOCAL_C_INCLUDES :=
-LOCAL_CFLAGS :=
-LOCAL_CPPFLAGS :=
+# Copyright (C) 2009 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.
+#
+
+# this file is included repeatedly from Android-portable.mk files in order to clean
+# the module-specific variables from the environment,
+
+$(call clear-src-tags)
+
+# Note: As a special exception, we don't want to clear LOCAL_PATH
+$(call clear-vars, $(filter-out LOCAL_PATH,$(modules-LOCALS:%=LOCAL_%)))
diff --git a/build/core/default-application.mk b/build/core/default-application.mk
new file mode 100644
index 0000000..9f56d68
--- /dev/null
+++ b/build/core/default-application.mk
@@ -0,0 +1,23 @@
+# Copyright (C) 2010 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.
+#
+
+# This is the default Application.mk that is being used for applications
+# that don't provide $PROJECT_PATH/jni/Application.mk
+#
+APP_PROJECT_PATH := $(GDK_PROJECT_PATH)
+
+# We expect the build script to be located here
+APP_BUILD_SCRIPT := $(APP_PROJECT_PATH)/jni/Android-portable.mk
+
diff --git a/build/core/definitions.mk b/build/core/definitions.mk
new file mode 100644
index 0000000..7b1a7ff
--- /dev/null
+++ b/build/core/definitions.mk
@@ -0,0 +1,1285 @@
+# We use the GNU Make Standard Library
+include $(GDK_ROOT)/build/gmsl/gmsl
+
+# -----------------------------------------------------------------------------
+# Macro : empty
+# Returns : an empty macro
+# Usage : $(empty)
+# -----------------------------------------------------------------------------
+empty :=
+
+# -----------------------------------------------------------------------------
+# Macro : space
+# Returns : a single space
+# Usage : $(space)
+# -----------------------------------------------------------------------------
+space := $(empty) $(empty)
+
+# -----------------------------------------------------------------------------
+# Function : last2
+# Arguments: a list
+# Returns : the penultimate (next-to-last) element of a list
+# Usage : $(call last2, <LIST>)
+# -----------------------------------------------------------------------------
+last2 = $(word $(words $1), x $1)
+
+# -----------------------------------------------------------------------------
+# Function : last3
+# Arguments: a list
+# Returns : the antepenultimate (second-next-to-last) element of a list
+# Usage : $(call last3, <LIST>)
+# -----------------------------------------------------------------------------
+last3 = $(word $(words $1), x x $1)
+
+# -----------------------------------------------------------------------------
+# Function : remove-duplicates
+# Arguments: a list
+# Returns : the list with duplicate items removed, order is preserved.
+# Usage : $(call remove-duplicates, <LIST>)
+# Note : This is equivalent to the 'uniq' function provided by GMSL,
+# however this implementation is non-recursive and *much*
+# faster. It will also not explode the stack with a lot of
+# items like 'uniq' does.
+# -----------------------------------------------------------------------------
+remove-duplicates = $(strip \
+ $(eval __uniq_ret :=) \
+ $(foreach __uniq_item,$1,\
+ $(if $(findstring $(__uniq_item),$(__uniq_ret)),,\
+ $(eval __uniq_ret += $(__uniq_item))\
+ )\
+ )\
+ $(__uniq_ret))
+
+# -----------------------------------------------------------------------------
+# Macro : this-makefile
+# Returns : the name of the current Makefile in the inclusion stack
+# Usage : $(this-makefile)
+# -----------------------------------------------------------------------------
+this-makefile = $(lastword $(MAKEFILE_LIST))
+
+# -----------------------------------------------------------------------------
+# Macro : local-makefile
+# Returns : the name of the last parsed Android-portable.mk file
+# Usage : $(local-makefile)
+# -----------------------------------------------------------------------------
+local-makefile = $(lastword $(filter %Android-portable.mk,$(MAKEFILE_LIST)))
+
+# -----------------------------------------------------------------------------
+# Function : assert-defined
+# Arguments: 1: list of variable names
+# Returns : None
+# Usage : $(call assert-defined, VAR1 VAR2 VAR3...)
+# Rationale: Checks that all variables listed in $1 are defined, or abort the
+# build
+# -----------------------------------------------------------------------------
+assert-defined = $(foreach __varname,$(strip $1),\
+ $(if $(strip $($(__varname))),,\
+ $(call __gdk_error, Assertion failure: $(__varname) is not defined)\
+ )\
+)
+
+# -----------------------------------------------------------------------------
+# Function : clear-vars
+# Arguments: 1: list of variable names
+# 2: file where the variable should be defined
+# Returns : None
+# Usage : $(call clear-vars, VAR1 VAR2 VAR3...)
+# Rationale: Clears/undefines all variables in argument list
+# -----------------------------------------------------------------------------
+clear-vars = $(foreach __varname,$1,$(eval $(__varname) := $(empty)))
+
+# -----------------------------------------------------------------------------
+# Function : check-required-vars
+# Arguments: 1: list of variable names
+# 2: file where the variable(s) should be defined
+# Returns : None
+# Usage : $(call check-required-vars, VAR1 VAR2 VAR3..., <file>)
+# Rationale: Checks that all required vars listed in $1 were defined by $2
+# or abort the build with an error
+# -----------------------------------------------------------------------------
+check-required-vars = $(foreach __varname,$1,\
+ $(if $(strip $($(__varname))),,\
+ $(call __gdk_info, Required variable $(__varname) is not defined by $2)\
+ $(call __gdk_error,Aborting)\
+ )\
+)
+
+# -----------------------------------------------------------------------------
+# Function : host-path
+# Arguments: 1: file path
+# Returns : file path, as understood by the host file system
+# Usage : $(call host-path,<path>)
+# Rationale: This function is used to translate Cygwin paths into
+# Windows-specific ones. On other platforms, it will just
+# return its argument.
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),windows)
+host-path = $(if $(strip $1),$(call cygwin-to-host-path,$1))
+else
+host-path = $1
+endif
+
+# -----------------------------------------------------------------------------
+# Function : host-c-includes
+# Arguments: 1: list of file paths (e.g. "foo bar")
+# Returns : list of include compiler options (e.g. "-Ifoo -Ibar")
+# Usage : $(call host-c-includes,<paths>)
+# Rationale: This function is used to translate Cygwin paths into
+# Windows-specific ones. On other platforms, it will just
+# return its argument.
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),windows)
+host-c-includes = $(patsubst %,-I%,$(call host-path,$1))
+else
+host-c-includes = $(1:%=-I%)
+endif
+
+
+# -----------------------------------------------------------------------------
+# Function : link-whole-archives
+# Arguments: 1: list of whole static libraries
+# Returns : linker flags to use the whole static libraries
+# Usage : $(call link-whole-archives,<libraries>)
+# Rationale: This function is used to put the list of whole static libraries
+# inside a -Wl,--whole-archive ... -Wl,--no-whole-archive block.
+# If the list is empty, it returns an empty string.
+# This function also calls host-path to translate the library
+# paths.
+# -----------------------------------------------------------------------------
+link-whole-archives = $(if $(strip $1),$(call link-whole-archive-flags,$1))
+link-whole-archive-flags = -Wl,--whole-archive $(call host-path,$1) -Wl,--no-whole-archive
+
+# =============================================================================
+#
+# Modules database
+#
+# The following declarations are used to manage the list of modules
+# defined in application's Android-portable.mk files.
+#
+# Technical note:
+# We use __gdk_modules to hold the list of all modules corresponding
+# to a given application.
+#
+# For each module 'foo', __gdk_modules.foo.<field> is used
+# to store module-specific information.
+#
+# type -> type of module (e.g. 'static', 'shared', ...)
+# depends -> list of other modules this module depends on
+#
+# Also, LOCAL_XXXX values defined for a module are recorded in XXXX, e.g.:
+#
+# PATH -> recorded LOCAL_PATH for the module
+# CFLAGS -> recorded LOCAL_CFLAGS for the module
+# ...
+#
+# Some of these are created by build scripts like BUILD_STATIC_LIBRARY:
+#
+# MAKEFILE -> The Android-portable.mk where the module is defined.
+# LDFLAGS -> Final linker flags
+# OBJECTS -> List of module objects
+# BUILT_MODULE -> location of module built file (e.g. obj/<app>/<abi>/libfoo.so)
+#
+# Note that some modules are never installed (e.g. static libraries).
+#
+# =============================================================================
+
+# The list of LOCAL_XXXX variables that are recorded for each module definition
+# These are documented by docs/ANDROID-MK.TXT. Exception is LOCAL_MODULE
+#
+modules-LOCALS := \
+ MODULE \
+ MODULE_FILENAME \
+ PATH \
+ SRC_FILES \
+ CPP_EXTENSION \
+ C_INCLUDES \
+ CFLAGS \
+ CXXFLAGS \
+ CPPFLAGS
+
+# The following are generated by the build scripts themselves
+
+# LOCAL_MAKEFILE will contain the path to the Android-portable.mk defining the module
+modules-LOCALS += MAKEFILE
+
+# LOCAL_OBJECTS will contain the list of object files generated from the
+# module's sources, if any.
+modules-LOCALS += OBJECTS
+
+# LOCAL_BUILT_MODULE will contain the location of the symbolic version of
+# the generated module (i.e. the one containing all symbols used during
+# native debugging). It is generally under $PROJECT/obj/local/
+modules-LOCALS += BUILT_MODULE
+
+# LOCAL_OBJS_DIR will contain the location where the object files for
+# this module will be stored. Usually $PROJECT/obj/local/<module>/obj
+modules-LOCALS += OBJS_DIR
+
+# LOCAL_INSTALLED will contain the location of the installed version
+# of the module. Usually $PROJECT/libs/<abi>/<prefix><module><suffix>
+# where <prefix> and <suffix> depend on the module class.
+modules-LOCALS += INSTALLED
+
+# LOCAL_MODULE_CLASS will contain the type of the module
+# (e.g. STATIC_LIBRARY, SHARED_LIBRARY, etc...)
+modules-LOCALS += MODULE_CLASS
+
+# the list of managed fields per module
+modules-fields = depends \
+ $(modules-LOCALS)
+
+# -----------------------------------------------------------------------------
+# Function : modules-clear
+# Arguments: None
+# Returns : None
+# Usage : $(call modules-clear)
+# Rationale: clears the list of defined modules known by the build system
+# -----------------------------------------------------------------------------
+modules-clear = \
+ $(foreach __mod,$(__gdk_modules),\
+ $(foreach __field,$(modules-fields),\
+ $(eval __gdk_modules.$(__mod).$(__field) := $(empty))\
+ )\
+ )\
+ $(eval __gdk_modules := $(empty_set)) \
+ $(eval __gdk_top_modules := $(empty)) \
+ $(eval __gdk_import_list := $(empty)) \
+ $(eval __gdk_import_depth := $(empty))
+
+# -----------------------------------------------------------------------------
+# Function : modules-get-list
+# Arguments: None
+# Returns : The list of all recorded modules
+# Usage : $(call modules-get-list)
+# -----------------------------------------------------------------------------
+modules-get-list = $(__gdk_modules)
+
+# -----------------------------------------------------------------------------
+# Function : modules-get-top-list
+# Arguments: None
+# Returns : The list of all recorded non-imported modules
+# Usage : $(call modules-get-top-list)
+# -----------------------------------------------------------------------------
+modules-get-top-list = $(__gdk_top_modules)
+
+# -----------------------------------------------------------------------------
+# Function : module-add
+# Arguments: 1: module name
+# Returns : None
+# Usage : $(call module-add,<modulename>)
+# Rationale: add a new module. If it is already defined, print an error message
+# and abort. This will record all LOCAL_XXX variables for the module.
+# -----------------------------------------------------------------------------
+module-add = \
+ $(call assert-defined,LOCAL_MAKEFILE LOCAL_BUILT_MODULE LOCAL_OBJS_DIR LOCAL_MODULE_CLASS)\
+ $(if $(call set_is_member,$(__gdk_modules),$1),\
+ $(call __gdk_info,Trying to define local module '$1' in $(LOCAL_MAKEFILE).)\
+ $(call __gdk_info,But this module was already defined by $(__gdk_modules.$1.MAKEFILE).)\
+ $(call __gdk_error,Aborting.)\
+ )\
+ $(eval __gdk_modules := $(call set_insert,$(__gdk_modules),$1))\
+ $(if $(strip $(__gdk_import_depth)),,\
+ $(eval __gdk_top_modules := $(call set_insert,$(__gdk_top_modules),$1))\
+ )\
+ $(if $(call module-class-is-installable,$(LOCAL_MODULE_CLASS)),\
+ $(eval LOCAL_INSTALLED := $(GDK_APP_DST_DIR)/$(notdir $(LOCAL_BUILT_MODULE)))\
+ )\
+ $(foreach __local,$(modules-LOCALS),\
+ $(eval __gdk_modules.$1.$(__local) := $(LOCAL_$(__local)))\
+ )
+
+
+# Retrieve the class of module $1
+module-get-class = $(__gdk_modules.$1.MODULE_CLASS)
+
+# Retrieve built location of module $1
+module-get-built = $(__gdk_modules.$1.BUILT_MODULE)
+
+# Returns $(true) is module $1 is installable
+# An installable module is one that will be copied to $PROJECT/libs/<abi>/
+# (e.g. shared libraries).
+#
+module-is-installable = $(call module-class-is-installable,$(call module-get-class,$1))
+
+# Returns $(true) if module $1 is prebuilt
+# A prebuilt module is one declared with BUILD_PREBUILT_SHARED_LIBRARY or
+# BUILD_PREBUILT_STATIC_LIBRARY
+#
+module-is-prebuilt = $(call module-class-is-prebuilt,$(call module-get-class,$1))
+
+# -----------------------------------------------------------------------------
+# Function : module-get-export
+# Arguments: 1: module name
+# 2: export variable name without LOCAL_EXPORT_ prefix (e.g. 'CFLAGS')
+# Returns : Exported value
+# Usage : $(call module-get-export,<modulename>,<varname>)
+# Rationale: Return the recorded value of LOCAL_EXPORT_$2, if any, for module $1
+# -----------------------------------------------------------------------------
+module-get-export = $(__gdk_modules.$1.EXPORT_$2)
+
+# -----------------------------------------------------------------------------
+# Function : module-get-listed-export
+# Arguments: 1: list of module names
+# 2: export variable name without LOCAL_EXPORT_ prefix (e.g. 'CFLAGS')
+# Returns : Exported values
+# Usage : $(call module-get-listed-export,<module-list>,<varname>)
+# Rationale: Return the recorded value of LOCAL_EXPORT_$2, if any, for modules
+# listed in $1.
+# -----------------------------------------------------------------------------
+module-get-listed-export = $(strip \
+ $(foreach __listed_module,$1,\
+ $(call module-get-export,$(__listed_module),$2)\
+ ))
+
+# -----------------------------------------------------------------------------
+# Function : modules-restore-locals
+# Arguments: 1: module name
+# Returns : None
+# Usage : $(call module-restore-locals,<modulename>)
+# Rationale: Restore the recorded LOCAL_XXX definitions for a given module.
+# -----------------------------------------------------------------------------
+module-restore-locals = \
+ $(foreach __local,$(modules-LOCALS),\
+ $(eval LOCAL_$(__local) := $(__gdk_modules.$1.$(__local)))\
+ )
+
+# Dump all module information. Only use this for debugging
+modules-dump-database = \
+ $(info Modules: $(__gdk_modules)) \
+ $(foreach __mod,$(__gdk_modules),\
+ $(info $(space)$(space)$(__mod):)\
+ $(foreach __field,$(modules-fields),\
+ $(info $(space)$(space)$(space)$(space)$(__field): $(__gdk_modules.$(__mod).$(__field)))\
+ )\
+ )\
+ $(info --- end of modules list)
+
+
+# -----------------------------------------------------------------------------
+# Function : module-add-static-depends
+# Arguments: 1: module name
+# 2: list/set of static library modules this module depends on.
+# Returns : None
+# Usage : $(call module-add-static-depends,<modulename>,<list of module names>)
+# Rationale: Record that a module depends on a set of static libraries.
+# Use module-get-static-dependencies to retrieve final list.
+# -----------------------------------------------------------------------------
+module-add-static-depends = \
+ $(call module-add-depends-any,$1,$2,depends) \
+
+# -----------------------------------------------------------------------------
+# Function : module-add-shared-depends
+# Arguments: 1: module name
+# 2: list/set of shared library modules this module depends on.
+# Returns : None
+# Usage : $(call module-add-shared-depends,<modulename>,<list of module names>)
+# Rationale: Record that a module depends on a set of shared libraries.
+# Use modulge-get-shared-dependencies to retrieve final list.
+# -----------------------------------------------------------------------------
+module-add-shared-depends = \
+ $(call module-add-depends-any,$1,$2,depends) \
+
+# Used internally by module-add-static-depends and module-add-shared-depends
+# NOTE: this function must not modify the existing dependency order when new depends are added.
+#
+module-add-depends-any = \
+ $(eval __gdk_modules.$1.$3 += $(filter-out $(__gdk_modules.$1.$3),$(call strip-lib-prefix,$2)))
+
+# Used to recompute all dependencies once all module information has been recorded.
+#
+modules-compute-dependencies = \
+ $(foreach __module,$(__gdk_modules),\
+ $(call module-compute-depends,$(__module))\
+ )
+
+module-compute-depends = \
+ $(call module-add-static-depends,$1,$(__gdk_modules.$1.STATIC_LIBRARIES))\
+ $(call module-add-static-depends,$1,$(__gdk_modules.$1.WHOLE_STATIC_LIBRARIES))\
+ $(call module-add-shared-depends,$1,$(__gdk_modules.$1.SHARED_LIBRARIES))\
+
+module-get-installed = $(__gdk_modules.$1.INSTALLED)
+
+# -----------------------------------------------------------------------------
+# Function : modules-get-all-dependencies
+# Arguments: 1: list of module names
+# Returns : List of all the modules $1 depends on transitively.
+# Usage : $(call modules-all-get-dependencies,<list of module names>)
+# Rationale: This computes the closure of all module dependencies starting from $1
+# -----------------------------------------------------------------------------
+module-get-all-dependencies = \
+ $(strip $(call modules-get-closure,$1,depends))
+
+modules-get-closure = \
+ $(eval __closure_deps := $(strip $1)) \
+ $(eval __closure_wq := $(__closure_deps)) \
+ $(eval __closure_field := $(strip $2)) \
+ $(call modules-closure)\
+ $(__closure_deps)
+
+# Used internally by modules-get-dependencies
+# Note the tricky use of conditional recursion to work around the fact that
+# the GNU Make language does not have any conditional looping construct
+# like 'while'.
+#
+modules-closure = \
+ $(eval __closure_mod := $(call first,$(__closure_wq))) \
+ $(eval __closure_wq := $(call rest,$(__closure_wq))) \
+ $(eval __closure_new := $(filter-out $(__closure_deps),$(__gdk_modules.$(__closure_mod).$(__closure_field))))\
+ $(eval __closure_deps += $(__closure_new)) \
+ $(eval __closure_wq := $(strip $(__closure_wq) $(__closure_new)))\
+ $(if $(__closure_wq),$(call modules-closure)) \
+
+# Return the C++ extension of a given module
+#
+module-get-cpp-extension = $(strip \
+ $(if $(__gdk_modules.$1.CPP_EXTENSION),\
+ $(__gdk_modules.$1.CPP_EXTENSION),\
+ .cpp\
+ ))
+
+# Return the list of C++ sources of a given module
+#
+module-get-c++-sources = \
+ $(filter %$(call module-get-cpp-extension,$1),$(__gdk_modules.$1.SRC_FILES))
+
+# Returns true if a module has C++ sources
+#
+module-has-c++ = $(strip $(call module-get-c++-sources,$1))
+
+# Add C++ dependencies to any module that has C++ sources.
+# $1: list of C++ runtime static libraries (if any)
+# $2: list of C++ runtime shared libraries (if any)
+#
+modules-add-c++-dependencies = \
+ $(foreach __module,$(__gdk_modules),\
+ $(if $(call module-has-c++,$(__module)),\
+ $(call gdk_log,Module '$(__module)' has C++ sources)\
+ $(call module-add-c++-deps,$(__module),$1,$2),\
+ )\
+ )
+
+# Add standard C++ dependencies to a given module
+#
+# $1: module name
+# $2: list of C++ runtime static libraries (if any)
+# $3: list of C++ runtime shared libraries (if any)
+#
+module-add-c++-deps = \
+ $(eval __gdk_modules.$1.STATIC_LIBRARIES += $(2))\
+ $(eval __gdk_modules.$1.SHARED_LIBRARIES += $(3))
+
+
+# =============================================================================
+#
+# Utility functions
+#
+# =============================================================================
+
+# -----------------------------------------------------------------------------
+# Function : parent-dir
+# Arguments: 1: path
+# Returns : Parent dir or path of $1, with final separator removed.
+# -----------------------------------------------------------------------------
+parent-dir = $(patsubst %/,%,$(dir $1))
+
+
+# -----------------------------------------------------------------------------
+# Function : pretty-dir
+# Arguments: 1: path
+# Returns : Remove GDK_PROJECT_PATH prefix from a given path. This can be
+# used to perform pretty-printing for logs.
+# -----------------------------------------------------------------------------
+pretty-dir = $(patsubst $(GDK_ROOT)/%,<GDK>/%,\
+ $(patsubst $(GDK_PROJECT_PATH)/%,%,$1))
+
+# -----------------------------------------------------------------------------
+# Function : check-user-define
+# Arguments: 1: name of variable that must be defined by the user
+# 2: name of Makefile where the variable should be defined
+# 3: name/description of the Makefile where the check is done, which
+# must be included by $2
+# Returns : None
+# -----------------------------------------------------------------------------
+check-user-define = $(if $(strip $($1)),,\
+ $(call __gdk_error,Missing $1 before including $3 in $2))
+
+# -----------------------------------------------------------------------------
+# This is used to check that LOCAL_MODULE is properly defined by an Android-portable.mk
+# file before including one of the $(BUILD_SHARED_LIBRARY), etc... files.
+#
+# Function : check-user-LOCAL_MODULE
+# Arguments: 1: name/description of the included build Makefile where the
+# check is done
+# Returns : None
+# Usage : $(call check-user-LOCAL_MODULE, BUILD_SHARED_LIBRARY)
+# -----------------------------------------------------------------------------
+check-defined-LOCAL_MODULE = \
+ $(call check-user-define,LOCAL_MODULE,$(local-makefile),$(1)) \
+ $(if $(call seq,$(words $(LOCAL_MODULE)),1),,\
+ $(call __gdk_info,LOCAL_MODULE definition in $(local-makefile) must not contain space)\
+ $(call __gdk_error,Please correct error. Aborting)\
+ )
+
+# -----------------------------------------------------------------------------
+# This is used to check that LOCAL_MODULE_FILENAME, if defined, is correct.
+#
+# Function : check-user-LOCAL_MODULE_FILENAME
+# Returns : None
+# Usage : $(call check-user-LOCAL_MODULE_FILENAME)
+# -----------------------------------------------------------------------------
+check-LOCAL_MODULE_FILENAME = \
+ $(if $(strip $(LOCAL_MODULE_FILENAME)),\
+ $(if $(call seq,$(words $(LOCAL_MODULE_FILENAME)),1),,\
+ $(call __gdk_info,$(LOCAL_MAKEFILE):$(LOCAL_MODULE): LOCAL_MODULE_FILENAME must not contain spaces)\
+ $(call __gdk_error,Plase correct error. Aborting)\
+ )\
+ $(if $(filter %.a %.so,$(LOCAL_MODULE_FILENAME)),\
+ $(call __gdk_info,$(LOCAL_MAKEFILE):$(LOCAL_MODULE): LOCAL_MODULE_FILENAME should not include file extensions)\
+ )\
+ )
+
+# -----------------------------------------------------------------------------
+# Function : handle-module-filename
+# Arguments : 1: default file prefix
+# 2: file suffix
+# Returns : None
+# Usage : $(call handle-module-filename,<prefix>,<suffix>)
+# Rationale : To be used to check and or set the module's filename through
+# the LOCAL_MODULE_FILENAME variable.
+# -----------------------------------------------------------------------------
+handle-module-filename = $(eval $(call ev-handle-module-filename,$1,$2))
+
+#
+# Check that LOCAL_MODULE_FILENAME is properly defined
+# - with one single item
+# - without a library file extension
+# - with no directory separators
+#
+define ev-check-module-filename
+ifneq (1,$$(words $$(LOCAL_MODULE_FILENAME)))
+ $$(call __gdk_info,$$(LOCAL_MAKEFILE):$$(LOCAL_MODULE): LOCAL_MODULE_FILENAME must not contain any space)
+ $$(call __gdk_error,Aborting)
+endif
+ifneq (,$$(filter %.a %.so,$$(LOCAL_MODULE_FILENAME)))
+ $$(call __gdk_info,$$(LOCAL_MAKEFILE):$$(LOCAL_MODULE): LOCAL_MODULE_FILENAME must not contain a file extension)
+ $$(call __gdk_error,Aborting)
+endif
+ifneq (1,$$(words $$(subst /, ,$$(LOCAL_MODULE_FILENAME))))
+ $$(call __gdk_info,$$(LOCAL_MAKEFILE):$$(LOCAL_MODULE): LOCAL_MODULE_FILENAME must not contain directory separators)
+ $$(call __gdk_error,Aborting)
+endif
+endef
+
+#
+# Check the definition of LOCAL_MODULE_FILENAME. If none exists,
+# infer it from the LOCAL_MODULE name.
+#
+# $1: default file prefix
+# $2: default file suffix
+#
+define ev-handle-module-filename
+LOCAL_MODULE_FILENAME := $$(strip $$(LOCAL_MODULE_FILENAME))
+ifndef LOCAL_MODULE_FILENAME
+ LOCAL_MODULE_FILENAME := $1$$(LOCAL_MODULE)
+endif
+$$(eval $$(call ev-check-module-filename))
+LOCAL_MODULE_FILENAME := $$(LOCAL_MODULE_FILENAME)$2
+endef
+
+handle-prebuilt-module-filename = $(eval $(call ev-handle-prebuilt-module-filename,$1))
+
+#
+# Check the definition of LOCAL_MODULE_FILENAME for a _prebuilt_ module.
+# If none exists, infer it from $(LOCAL_SRC_FILES)
+#
+# $1: default file suffix
+#
+define ev-handle-prebuilt-module-filename
+LOCAL_MODULE_FILENAME := $$(strip $$(LOCAL_MODULE_FILENAME))
+ifndef LOCAL_MODULE_FILENAME
+ LOCAL_MODULE_FILENAME := $$(notdir $(LOCAL_SRC_FILES))
+ LOCAL_MODULE_FILENAME := $$(LOCAL_MODULE_FILENAME:%.a=%)
+ LOCAL_MODULE_FILENAME := $$(LOCAL_MODULE_FILENAME:%.so=%)
+endif
+LOCAL_MODULE_FILENAME := $$(LOCAL_MODULE_FILENAME)$1
+$$(eval $$(call ev-check-module-filename))
+endef
+
+
+# -----------------------------------------------------------------------------
+# Function : handle-module-built
+# Returns : None
+# Usage : $(call handle-module-built)
+# Rationale : To be used to automatically compute the location of the generated
+# binary file, and the directory where to place its object files.
+# -----------------------------------------------------------------------------
+handle-module-built = \
+ $(eval LOCAL_BUILT_MODULE := $(TARGET_OUT)/$(LOCAL_MODULE_FILENAME))\
+ $(eval LOCAL_OBJS_DIR := $(TARGET_OBJS)/$(LOCAL_MODULE))
+
+# -----------------------------------------------------------------------------
+# Strip any 'lib' prefix in front of a given string.
+#
+# Function : strip-lib-prefix
+# Arguments: 1: module name
+# Returns : module name, without any 'lib' prefix if any
+# Usage : $(call strip-lib-prefix,$(LOCAL_MODULE))
+# -----------------------------------------------------------------------------
+strip-lib-prefix = $(1:lib%=%)
+
+# -----------------------------------------------------------------------------
+# This is used to strip any lib prefix from LOCAL_MODULE, then check that
+# the corresponding module name is not already defined.
+#
+# Function : check-user-LOCAL_MODULE
+# Arguments: 1: path of Android-portable.mk where this LOCAL_MODULE is defined
+# Returns : None
+# Usage : $(call check-LOCAL_MODULE,$(LOCAL_MAKEFILE))
+# -----------------------------------------------------------------------------
+check-LOCAL_MODULE = \
+ $(eval LOCAL_MODULE := $$(call strip-lib-prefix,$$(LOCAL_MODULE)))
+
+# -----------------------------------------------------------------------------
+# Macro : my-dir
+# Returns : the directory of the current Makefile
+# Usage : $(my-dir)
+# -----------------------------------------------------------------------------
+my-dir = $(call parent-dir,$(lastword $(MAKEFILE_LIST)))
+
+# -----------------------------------------------------------------------------
+# Function : all-makefiles-under
+# Arguments: 1: directory path
+# Returns : a list of all makefiles immediately below some directory
+# Usage : $(call all-makefiles-under, <some path>)
+# -----------------------------------------------------------------------------
+all-makefiles-under = $(wildcard $1/*/Android-portable.mk)
+
+# -----------------------------------------------------------------------------
+# Macro : all-subdir-makefiles
+# Returns : list of all makefiles in subdirectories of the current Makefile's
+# location
+# Usage : $(all-subdir-makefiles)
+# -----------------------------------------------------------------------------
+all-subdir-makefiles = $(call all-makefiles-under,$(call my-dir))
+
+# =============================================================================
+#
+# Source file tagging support.
+#
+# Each source file listed in LOCAL_SRC_FILES can have any number of
+# 'tags' associated to it. A tag name must not contain space, and its
+# usage can vary.
+#
+# For example, the 'debug' tag is used to sources that must be built
+# in debug mode, the 'arm' tag is used for sources that must be built
+# using the 32-bit instruction set on ARM platforms, and 'neon' is used
+# for sources that must be built with ARM Advanced SIMD (a.k.a. NEON)
+# support.
+#
+# More tags might be introduced in the future.
+#
+# LOCAL_SRC_TAGS contains the list of all tags used (initially empty)
+# LOCAL_SRC_FILES contains the list of all source files.
+# LOCAL_SRC_TAG.<tagname> contains the set of source file names tagged
+# with <tagname>
+# LOCAL_SRC_FILES_TAGS.<filename> contains the set of tags for a given
+# source file name
+#
+# Tags are processed by a toolchain-specific function (e.g. TARGET-compute-cflags)
+# which will call various functions to compute source-file specific settings.
+# These are currently stored as:
+#
+# LOCAL_SRC_FILES_TARGET_CFLAGS.<filename> contains the list of
+# target-specific C compiler flags used to compile a given
+# source file. This is set by the function TARGET-set-cflags
+# defined in the toolchain's setup.mk script.
+#
+# LOCAL_SRC_FILES_TEXT.<filename> contains the 'text' that will be
+# displayed along the label of the build output line. For example
+# 'thumb' or 'arm ' with ARM-based toolchains.
+#
+# =============================================================================
+
+# -----------------------------------------------------------------------------
+# Macro : clear-all-src-tags
+# Returns : remove all source file tags and associated data.
+# Usage : $(clear-all-src-tags)
+# -----------------------------------------------------------------------------
+clear-all-src-tags = \
+$(foreach __tag,$(LOCAL_SRC_TAGS), \
+ $(eval LOCAL_SRC_TAG.$(__tag) := $(empty)) \
+) \
+$(foreach __src,$(LOCAL_SRC_FILES), \
+ $(eval LOCAL_SRC_FILES_TAGS.$(__src) := $(empty)) \
+ $(eval LOCAL_SRC_FILES_TARGET_CFLAGS.$(__src) := $(empty)) \
+ $(eval LOCAL_SRC_FILES_TEXT.$(__src) := $(empty)) \
+) \
+$(eval LOCAL_SRC_TAGS := $(empty_set))
+
+# -----------------------------------------------------------------------------
+# Macro : tag-src-files
+# Arguments: 1: list of source files to tag
+# 2: tag name (must not contain space)
+# Usage : $(call tag-src-files,<list-of-source-files>,<tagname>)
+# Rationale: Add a tag to a list of source files
+# -----------------------------------------------------------------------------
+tag-src-files = \
+$(eval LOCAL_SRC_TAGS := $(call set_insert,$2,$(LOCAL_SRC_TAGS))) \
+$(eval LOCAL_SRC_TAG.$2 := $(call set_union,$1,$(LOCAL_SRC_TAG.$2))) \
+$(foreach __src,$1, \
+ $(eval LOCAL_SRC_FILES_TAGS.$(__src) += $2) \
+)
+
+# -----------------------------------------------------------------------------
+# Macro : get-src-files-with-tag
+# Arguments: 1: tag name
+# Usage : $(call get-src-files-with-tag,<tagname>)
+# Return : The list of source file names that have been tagged with <tagname>
+# -----------------------------------------------------------------------------
+get-src-files-with-tag = $(LOCAL_SRC_TAG.$1)
+
+# -----------------------------------------------------------------------------
+# Macro : get-src-files-without-tag
+# Arguments: 1: tag name
+# Usage : $(call get-src-files-without-tag,<tagname>)
+# Return : The list of source file names that have NOT been tagged with <tagname>
+# -----------------------------------------------------------------------------
+get-src-files-without-tag = $(filter-out $(LOCAL_SRC_TAG.$1),$(LOCAL_SRC_FILES))
+
+# -----------------------------------------------------------------------------
+# Macro : set-src-files-target-cflags
+# Arguments: 1: list of source files
+# 2: list of compiler flags
+# Usage : $(call set-src-files-target-cflags,<sources>,<flags>)
+# Rationale: Set or replace the set of compiler flags that will be applied
+# when building a given set of source files. This function should
+# normally be called from the toolchain-specific function that
+# computes all compiler flags for all source files.
+# -----------------------------------------------------------------------------
+set-src-files-target-cflags = $(foreach __src,$1,$(eval LOCAL_SRC_FILES_TARGET_CFLAGS.$(__src) := $2))
+
+# -----------------------------------------------------------------------------
+# Macro : add-src-files-target-cflags
+# Arguments: 1: list of source files
+# 2: list of compiler flags
+# Usage : $(call add-src-files-target-cflags,<sources>,<flags>)
+# Rationale: A variant of set-src-files-target-cflags that can be used
+# to append, instead of replace, compiler flags for specific
+# source files.
+# -----------------------------------------------------------------------------
+add-src-files-target-cflags = $(foreach __src,$1,$(eval LOCAL_SRC_FILES_TARGET_CFLAGS.$(__src) += $2))
+
+# -----------------------------------------------------------------------------
+# Macro : get-src-file-target-cflags
+# Arguments: 1: single source file name
+# Usage : $(call get-src-file-target-cflags,<source>)
+# Rationale: Return the set of target-specific compiler flags that must be
+# applied to a given source file. These must be set prior to this
+# call using set-src-files-target-cflags or add-src-files-target-cflags
+# -----------------------------------------------------------------------------
+get-src-file-target-cflags = $(LOCAL_SRC_FILES_TARGET_CFLAGS.$1)
+
+# -----------------------------------------------------------------------------
+# Macro : set-src-files-text
+# Arguments: 1: list of source files
+# 2: text
+# Usage : $(call set-src-files-text,<sources>,<text>)
+# Rationale: Set or replace the 'text' associated to a set of source files.
+# The text is a very short string that complements the build
+# label. For example, it will be either 'thumb' or 'arm ' for
+# ARM-based toolchains. This function must be called by the
+# toolchain-specific functions that processes all source files.
+# -----------------------------------------------------------------------------
+set-src-files-text = $(foreach __src,$1,$(eval LOCAL_SRC_FILES_TEXT.$(__src) := $2))
+
+# -----------------------------------------------------------------------------
+# Macro : get-src-file-text
+# Arguments: 1: single source file
+# Usage : $(call get-src-file-text,<source>)
+# Rationale: Return the 'text' associated to a given source file when
+# set-src-files-text was called.
+# -----------------------------------------------------------------------------
+get-src-file-text = $(LOCAL_SRC_FILES_TEXT.$1)
+
+# This should only be called for debugging the source files tagging system
+dump-src-file-tags = \
+$(info LOCAL_SRC_TAGS := $(LOCAL_SRC_TAGS)) \
+$(info LOCAL_SRC_FILES = $(LOCAL_SRC_FILES)) \
+$(foreach __tag,$(LOCAL_SRC_TAGS),$(info LOCAL_SRC_TAG.$(__tag) = $(LOCAL_SRC_TAG.$(__tag)))) \
+$(foreach __src,$(LOCAL_SRC_FILES),$(info LOCAL_SRC_FILES_TAGS.$(__src) = $(LOCAL_SRC_FILES_TAGS.$(__src)))) \
+$(info WITH arm = $(call get-src-files-with-tag,arm)) \
+$(info WITHOUT arm = $(call get-src-files-without-tag,arm)) \
+$(foreach __src,$(LOCAL_SRC_FILES),$(info LOCAL_SRC_FILES_TARGET_CFLAGS.$(__src) = $(LOCAL_SRC_FILES_TARGET_CFLAGS.$(__src)))) \
+$(foreach __src,$(LOCAL_SRC_FILES),$(info LOCAL_SRC_FILES_TEXT.$(__src) = $(LOCAL_SRC_FILES_TEXT.$(__src)))) \
+
+
+# =============================================================================
+#
+# Application.mk support
+#
+# =============================================================================
+
+# the list of variables that *must* be defined in Application.mk files
+GDK_APP_VARS_REQUIRED :=
+
+# the list of variables that *may* be defined in Application.mk files
+GDK_APP_VARS_OPTIONAL := APP_OPTIM APP_CPPFLAGS APP_CFLAGS APP_CXXFLAGS \
+ APP_PLATFORM APP_BUILD_SCRIPT APP_ABI APP_MODULES \
+ APP_PROJECT_PATH APP_STL
+
+# the list of all variables that may appear in an Application.mk file
+# or defined by the build scripts.
+GDK_APP_VARS := $(GDK_APP_VARS_REQUIRED) \
+ $(GDK_APP_VARS_OPTIONAL) \
+ APP_DEBUG \
+ APP_DEBUGGABLE \
+ APP_MANIFEST
+
+# =============================================================================
+#
+# Android.mk support
+#
+# =============================================================================
+
+# =============================================================================
+#
+# Build commands support
+#
+# =============================================================================
+
+# -----------------------------------------------------------------------------
+# Macro : hide
+# Returns : nothing
+# Usage : $(hide)<make commands>
+# Rationale: To be used as a prefix for Make build commands to hide them
+# by default during the build. To show them, set V=1 in your
+# environment or command-line.
+#
+# For example:
+#
+# foo.o: foo.c
+# -->|$(hide) <build-commands>
+#
+# Where '-->|' stands for a single tab character.
+#
+# -----------------------------------------------------------------------------
+ifeq ($(V),1)
+hide = $(empty)
+else
+hide = @
+endif
+
+# cmd-convert-deps
+#
+# Commands used to copy/convert the .d.org depency file generated by the
+# compiler into its final .d version.
+#
+# On windows, this myst convert the Windows paths to a format that our
+# Cygwin-based GNU Make can understand (i.e. C:/Foo => /cygdrive/c/Foo)
+#
+# On other platforms, this simply renames the file.
+#
+# NOTE: In certain cases, no dependency file will be generated by the
+# compiler (e.g. when compiling an assembly file as foo.s)
+#
+ifeq ($(HOST_OS),windows)
+cmd-convert-deps = \
+ ( if [ -f "$1.org" ]; then \
+ $(HOST_AWK) -f $(BUILD_AWK)/convert-deps-to-cygwin.awk $1.org > $1 && \
+ rm -f $1.org; \
+ fi )
+else
+cmd-convert-deps = \
+ ( if [ -f "$1.org" ]; then \
+ rm -f $1 && \
+ mv $1.org $1; \
+ fi )
+endif
+
+# This assumes that many variables have been pre-defined:
+# _SRC: source file
+# _OBJ: destination file
+# _CC: 'compiler' command
+# _FLAGS: 'compiler' flags
+# _TEXT: Display text (e.g. "Compile++ thumb", must be EXACTLY 17 chars long)
+#
+define ev-build-file
+$$(_OBJ): PRIVATE_SRC := $$(_SRC)
+$$(_OBJ): PRIVATE_OBJ := $$(_OBJ)
+$$(_OBJ): PRIVATE_DEPS := $$(call host-path,$$(_OBJ).d)
+$$(_OBJ): PRIVATE_MODULE := $$(LOCAL_MODULE)
+$$(_OBJ): PRIVATE_TEXT := "$$(_TEXT)"
+$$(_OBJ): PRIVATE_CC := $$(_CC)
+$$(_OBJ): PRIVATE_CFLAGS := $$(_FLAGS)
+$$(_OBJ): $$(_SRC) $$(LOCAL_MAKEFILE) $$(GDK_APP_APPLICATION_MK)
+ @mkdir -p $$(dir $$(PRIVATE_OBJ))
+ @echo "$$(PRIVATE_TEXT): $$(PRIVATE_MODULE) <= $$(notdir $$(PRIVATE_SRC))"
+ $(hide) $$(PRIVATE_CC) $$(PRIVATE_CFLAGS) $$(call host-path,$$(PRIVATE_SRC)) -o $$(call host-path,$$(PRIVATE_OBJ))
+endef
+
+# This assumes the same things than ev-build-file, but will handle
+# the definition of LOCAL_FILTER_ASM as well.
+define ev-build-source-file
+LOCAL_DEPENDENCY_DIRS += $$(dir $$(_OBJ))
+ifndef LOCAL_FILTER_ASM
+ # Trivial case: Directly generate an object file
+ $$(eval $$(call ev-build-file))
+else
+ # This is where things get hairy, we first transform
+ # the source into an assembler file, send it to the
+ # filter, then generate a final object file from it.
+ #
+
+ # First, remember the original settings and compute
+ # the location of our temporary files.
+ #
+ _ORG_SRC := $$(_SRC)
+ _ORG_OBJ := $$(_OBJ)
+ _ORG_FLAGS := $$(_FLAGS)
+ _ORG_TEXT := $$(_TEXT)
+
+ _OBJ_ASM_ORIGINAL := $$(patsubst %.o,%.s,$$(_ORG_OBJ))
+ _OBJ_ASM_FILTERED := $$(patsubst %.o,%.filtered.s,$$(_ORG_OBJ))
+
+ # If the source file is a plain assembler file, we're going to
+ # use it directly in our filter.
+ ifneq (,$$(filter %.s,$$(_SRC)))
+ _OBJ_ASM_ORIGINAL := $$(_SRC)
+ endif
+
+ #$$(info SRC=$$(_SRC) OBJ=$$(_OBJ) OBJ_ORIGINAL=$$(_OBJ_ASM_ORIGINAL) OBJ_FILTERED=$$(_OBJ_ASM_FILTERED))
+
+ # We need to transform the source into an assembly file, instead of
+ # an object. The proper way to do that depends on the file extension.
+ #
+ # For C and C++ source files, simply replace the -c by an -S in the
+ # compilation command (this forces the compiler to generate an
+ # assembly file).
+ #
+ # For assembler templates (which end in .S), replace the -c with -E
+ # to send it to the preprocessor instead.
+ #
+ # Don't do anything for plain assembly files (which end in .s)
+ #
+ ifeq (,$$(filter %.s,$$(_SRC)))
+ _OBJ := $$(_OBJ_ASM_ORIGINAL)
+ ifneq (,$$(filter %.S,$$(_SRC)))
+ _FLAGS := $$(patsubst -c,-E,$$(_ORG_FLAGS))
+ else
+ _FLAGS := $$(patsubst -c,-S,$$(_ORG_FLAGS))
+ endif
+ $$(eval $$(call ev-build-file))
+ endif
+
+ # Next, process the assembly file with the filter
+ $$(_OBJ_ASM_FILTERED): PRIVATE_SRC := $$(_OBJ_ASM_ORIGINAL)
+ $$(_OBJ_ASM_FILTERED): PRIVATE_DST := $$(_OBJ_ASM_FILTERED)
+ $$(_OBJ_ASM_FILTERED): PRIVATE_FILTER := $$(LOCAL_FILTER_ASM)
+ $$(_OBJ_ASM_FILTERED): PRIVATE_MODULE := $$(LOCAL_MODULE)
+ $$(_OBJ_ASM_FILTERED): $$(_OBJ_ASM_ORIGINAL)
+ @echo "AsmFilter : $$(PRIVATE_MODULE) <= $$(notdir $$(PRIVATE_SRC))"
+ $(hide) $$(PRIVATE_FILTER) $$(PRIVATE_SRC) $$(PRIVATE_DST)
+
+ # Then, generate the final object, we need to keep assembler-specific
+ # flags which look like -Wa,<option>:
+ _SRC := $$(_OBJ_ASM_FILTERED)
+ _OBJ := $$(_ORG_OBJ)
+ _FLAGS := $$(filter -Wa%,$$(_ORG_FLAGS)) -c
+ _TEXT := "Assembly "
+ $$(eval $$(call ev-build-file))
+endif
+endef
+
+# -----------------------------------------------------------------------------
+# Template : ev-compile-c-source
+# Arguments : 1: single C source file name (relative to LOCAL_PATH)
+# 2: target object file (without path)
+# Returns : None
+# Usage : $(eval $(call ev-compile-c-source,<srcfile>,<objfile>)
+# Rationale : Internal template evaluated by compile-c-source and
+# compile-s-source
+# -----------------------------------------------------------------------------
+define ev-compile-c-source
+_SRC:=$$(LOCAL_PATH)/$(1)
+_OBJ:=$$(LOCAL_OBJS_DIR)/$(2)
+
+_FLAGS := $$($$(my)CFLAGS) \
+ $$(call get-src-file-target-cflags,$(1)) \
+ $$(call host-c-includes,$$(LOCAL_C_INCLUDES) $$(LOCAL_PATH)) \
+ $$(LOCAL_CFLAGS) \
+ $$(GDK_APP_CFLAGS) \
+ $$(call host-c-includes,$$($(my)C_INCLUDES)) \
+ -c \
+
+_TEXT := "Compile Bitcode "
+_CC := $$(TARGET_CC)
+
+$$(eval $$(call ev-build-source-file))
+endef
+
+# -----------------------------------------------------------------------------
+# Function : compile-c-source
+# Arguments : 1: single C source file name (relative to LOCAL_PATH)
+# Returns : None
+# Usage : $(call compile-c-source,<srcfile>)
+# Rationale : Setup everything required to build a single C source file
+# -----------------------------------------------------------------------------
+compile-c-source = $(eval $(call ev-compile-c-source,$1,$(1:%.c=%.bc)))
+
+# -----------------------------------------------------------------------------
+# Function : compile-s-source
+# Arguments : 1: single Assembly source file name (relative to LOCAL_PATH)
+# Returns : None
+# Usage : $(call compile-s-source,<srcfile>)
+# Rationale : Setup everything required to build a single Assembly source file
+# -----------------------------------------------------------------------------
+compile-s-source = $(eval $(call ev-compile-c-source,$1,$(patsubst %.s,%.o,$(patsubst %.S,%.o,$1))))
+
+
+# -----------------------------------------------------------------------------
+# Template : ev-compile-cpp-source
+# Arguments : 1: single C++ source file name (relative to LOCAL_PATH)
+# 2: target object file (without path)
+# Returns : None
+# Usage : $(eval $(call ev-compile-cpp-source,<srcfile>,<objfile>)
+# Rationale : Internal template evaluated by compile-cpp-source
+# -----------------------------------------------------------------------------
+
+define ev-compile-cpp-source
+_SRC:=$$(LOCAL_PATH)/$(1)
+_OBJ:=$$(LOCAL_OBJS_DIR)/$(2)
+_FLAGS := $$($$(my)CXXFLAGS) \
+ $$(call get-src-file-target-cflags,$(1)) \
+ $$(call host-c-includes, $$(LOCAL_C_INCLUDES) $$(LOCAL_PATH)) \
+ $$(LOCAL_CFLAGS) \
+ $$(LOCAL_CPPFLAGS) \
+ $$(LOCAL_CXXFLAGS) \
+ $$(GDK_APP_CFLAGS) \
+ $$(GDK_APP_CPPFLAGS) \
+ $$(GDK_APP_CXXFLAGS) \
+ $$(call host-c-includes,$$($(my)C_INCLUDES)) \
+ -c \
+
+_CC := $$($$(my)CXX)
+_TEXT := "Compile++ Bitcode"
+
+$$(eval $$(call ev-build-source-file))
+endef
+
+# -----------------------------------------------------------------------------
+# Function : compile-cpp-source
+# Arguments : 1: single C++ source file name (relative to LOCAL_PATH)
+# Returns : None
+# Usage : $(call compile-c-source,<srcfile>)
+# Rationale : Setup everything required to build a single C++ source file
+# -----------------------------------------------------------------------------
+compile-cpp-source = $(eval $(call ev-compile-cpp-source,$1,$(1:%$(LOCAL_CPP_EXTENSION)=%.bc)))
+
+# -----------------------------------------------------------------------------
+# Command : cmd-install-file
+# Arguments : 1: source file
+# 2: destination file
+# Returns : None
+# Usage : $(call cmd-install-file,<srcfile>,<dstfile>)
+# Rationale : To be used as a Make build command to copy/install a file to
+# a given location.
+# -----------------------------------------------------------------------------
+define cmd-install-file
+@mkdir -p $(dir $2)
+$(hide) cp -fp $1 $2
+endef
+
+
+#
+# Module Cannot import module with spaces in tag: '$(__import_tag)')\
+# )\
+# $(if $(call set_is_member,$(__gdk_import_list),$(__import_tag)),\
+# $(call gdk_log,Skipping duplicate import for module with tag '$(__import_tag)')\
+# ,\
+# $(call gdk_log,Looking for imported module with tag '$(__import_tag)')\
+# $(eval __imported_path := $(call import-find-module,$(__import_tag)))\
+# $(if $(__imported_path),\
+# $(call gdk_log, Found in $(__imported_path))\
+# $(eval __gdk_import_depth := $(__gdk_import_depth)x) \
+# $(eval __gdk_import_list := $(call set_insert,$(__gdk_import_list),$(__import_tag)))\
+# $(eval include $(__imported_path)/Android-portable.mk)\
+# $(eval __gdk_import_depth := $(__gdk_import_depth:%x=%))\
+# ,\
+# $(call __gdk_info,$(call local-makefile): Cannot find module with tag '$(__import_tag)' in import path)\
+# $(call __gdk_info,Are you sure your GDK_MODULE_PATH variable is properly defined ?)\
+# $(call __gdk_info,The following directories were searched:)\
+# $(for __import_dir,$(__gdk_import_dirs),\
+# $(call __gdk_info, $(__import_dir))\
+# )\
+# $(call __gdk_error,Aborting.)\
+# )\
+# )
+
+# Only used for debugging
+#
+import-debug = \
+ $(info IMPORT DIRECTORIES:)\
+ $(foreach __dir,$(__gdk_import_dirs),\
+ $(info -- $(__dir))\
+ )\
+
+#
+# Module classes
+#
+GDK_MODULE_CLASSES :=
+
+# Register a new module class
+# $1: class name (e.g. STATIC_LIBRARY)
+# $2: optional file prefix (e.g. 'lib')
+# $3: optional file suffix (e.g. '.so')
+#
+module-class-register = \
+ $(eval GDK_MODULE_CLASSES += $1) \
+ $(eval GDK_MODULE_CLASS.$1.FILE_PREFIX := $2) \
+ $(eval GDK_MODULE_CLASS.$1.FILE_SUFFIX := $3) \
+ $(eval GDK_MODULE_CLASS.$1.INSTALLABLE := $(false)) \
+
+# Same a module-class-register, for installable modules
+#
+# An installable module is one that will be copied to $PROJECT/libs/<abi>/
+# during the GDK build.
+#
+# $1: class name
+# $2: optional file prefix
+# $3: optional file suffix
+#
+module-class-register-installable = \
+ $(call module-class-register,$1,$2,$3) \
+ $(eval GDK_MODULE_CLASS.$1.INSTALLABLE := $(true))
+
+module-class-set-prebuilt = \
+ $(eval GDK_MODULE_CLASS.$1.PREBUILT := $(true))
+
+# Returns $(true) if $1 is a valid/registered LOCAL_MODULE_CLASS value
+#
+module-class-check = $(call set_is_member,$(GDK_MODULE_CLASSES),$1)
+
+# Returns $(true) if $1 corresponds to an installable module class
+#
+module-class-is-installable = $(if $(GDK_MODULE_CLASS.$1.INSTALLABLE),$(true),$(false))
+
+# Returns $(true) if $1 corresponds to an installable module class
+#
+module-class-is-prebuilt = $(if $(GDK_MODULE_CLASS.$1.PREBUILT),$(true),$(false))
+
+#
+# Register valid module classes
+#
+
+# static libraries:
+# <foo> -> lib<foo>.a by default
+#$(call module-class-register,STATIC_LIBRARY,lib,.a)
+
+# shared libraries:
+# <foo> -> lib<foo>.so
+# a shared library is installable.
+#$(call module-class-register-installable,SHARED_LIBRARY,lib,.so)
+
+# bitcodes:
+# <foo> -> lib<foo>.bc
+$(call module-class-register-installable,BITCODE,lib,.bc)
+
+# executable
+# <foo> -> <foo>
+# an executable is installable.
+#$(call module-class-register-installable,EXECUTABLE,,)
+
+# prebuilt shared library
+# <foo> -> <foo> (we assume it is already well-named)
+# it is installable
+#$(call module-class-register-installable,PREBUILT_SHARED_LIBRARY,,)
+#$(call module-class-set-prebuilt,PREBUILT_SHARED_LIBRARY)
+
+# prebuilt static library
+# <foo> -> <foo> (we assume it is already well-named)
+#$(call module-class-register,PREBUILT_STATIC_LIBRARY,,)
+#$(call module-class-set-prebuilt,PREBUILT_STATIC_LIBRARY)
+
+#
+# C++ STL support
+#
+
+## The list of registered STL implementations we support
+#GDK_STL_LIST :=
+#
+## Used internally to register a given STL implementation, see below.
+##
+## $1: STL name as it appears in APP_STL (e.g. system)
+## $2: STL module name (e.g. cxx-stl/system)
+## $3: list of static libraries all modules will depend on
+## $4: list of shared libraries all modules will depend on
+##
+#gdk-stl-register = \
+# $(eval __gdk_stl := $(strip $1)) \
+# $(eval GDK_STL_LIST += $(__gdk_stl)) \
+# $(eval GDK_STL.$(__gdk_stl).IMPORT_MODULE := $(strip $2)) \
+# $(eval GDK_STL.$(__gdk_stl).STATIC_LIBS := $(strip $3)) \
+# $(eval GDK_STL.$(__gdk_stl).SHARED_LIBS := $(strip $4))
+#
+## Called to check that the value of APP_STL is a valid one.
+## $1: STL name as it apperas in APP_STL (e.g. 'system')
+##
+#gdk-stl-check = \
+# $(if $(call set_is_member,$(GDK_STL_LIST),$1),,\
+# $(call __gdk_info,Invalid APP_STL value: $1)\
+# $(call __gdk_info,Please use one of the following instead: $(GDK_STL_LIST))\
+# $(call __gdk_error,Aborting))
+#
+## Called before the top-level Android.mk is parsed to
+## select the STL implementation.
+## $1: STL name as it appears in APP_STL (e.g. system)
+##
+#gdk-stl-select = \
+# $(call import-module,$(GDK_STL.$1.IMPORT_MODULE))
+#
+## Called after all Android.mk files are parsed to add
+## proper STL dependencies to every C++ module.
+## $1: STL name as it appears in APP_STL (e.g. system)
+##
+##gdk-stl-add-dependencies = \
+# $(call modules-add-c++-dependencies,\
+# $(GDK_STL.$1.STATIC_LIBS),\
+# $(GDK_STL.$1.SHARED_LIBS))
+#
+##
+##
+#
+## Register the 'system' STL implementation
+##
+#$(call gdk-stl-register,\
+# system,\
+# cxx-stl/system,\
+# libstdc++,\
+# )
+#
+## Register the 'stlport_static' STL implementation
+##
+#$(call gdk-stl-register,\
+# stlport_static,\
+# cxx-stl/stlport,\
+# stlport_static,\
+# )
+#
+## Register the 'stlport_shared' STL implementation
+##
+#$(call gdk-stl-register,\
+# stlport_shared,\
+# cxx-stl/stlport,\
+# ,\
+# stlport_shared\
+# )
+#
+## Register the 'gnustl_static' STL implementation
+##
+#$(call gdk-stl-register,\
+# gnustl_static,\
+# cxx-stl/gnu-libstdc++,\
+# gnustl_static,\
+# \
+# )
+#
diff --git a/build/core/init.mk b/build/core/init.mk
index e899f19..290e0fe 100644
--- a/build/core/init.mk
+++ b/build/core/init.mk
@@ -1,9 +1,339 @@
-# We need borrow definitions.mk from NDK due to some predefines.
-# Like: $(call my-dir)
-include $(NDK_ROOT)/build/core/definitions.mk
+GDK_LOG := $(strip $(GDK_LOG))
-GDK_PLATFORM_ROOT := $(GDK_ROOT)/platforms/android-portable/arch-llvm
-GDK_TOOLCHAIN_ROOT := $(GDK_ROOT)/toolchains/llvm
+# Check that we have at least GNU Make 3.81
+# We do this by detecting whether 'lastword' is supported
+#
+MAKE_TEST := $(lastword a b c d e f)
+ifneq ($(MAKE_TEST),f)
+ $(error Android GDK: GNU Make version $(MAKE_VERSION) is too low (should be >= 3.81))
+endif
+ifdef GDK_LOG
+ $(info Android GDK: GNU Make version $(MAKE_VERSION) detected)
+endif
-CLEAR_VARS := $(GDK_ROOT)/build/core/clear-vars.mk
-BUILD_BITCODE := $(GDK_ROOT)/build/core/build-bitcode.mk
+# GDK_ROOT *must* be defined and point to the root of the GDK installation
+GDK_ROOT := $(strip $(GDK_ROOT))
+ifndef GDK_ROOT
+ $(error ERROR while including init.mk: GDK_ROOT must be defined !)
+endif
+ifneq ($(words $(GDK_ROOT)),1)
+ $(info,The Android GDK installation path contains spaces: '$(GDK_ROOT)')
+ $(error,Please fix the problem by reinstalling to a different location.)
+endif
+
+# ====================================================================
+#
+# Define a few useful variables and functions.
+# More stuff will follow in definitions.mk.
+#
+# ====================================================================
+
+# Used to output warnings and error from the library, it's possible to
+# disable any warnings or errors by overriding these definitions
+# manually or by setting GDK_NO_WARNINGS or GDK_NO_ERRORS
+
+__gdk_name := Android GDK
+__gdk_info = $(info $(__gdk_name): $1 $2 $3 $4 $5)
+__gdk_warning = $(warning $(__gdk_name): $1 $2 $3 $4 $5)
+__gdk_error = $(error $(__gdk_name): $1 $2 $3 $4 $5)
+
+ifdef GDK_NO_WARNINGS
+__gdk_warning :=
+endif
+ifdef GDK_NO_ERRORS
+__gdk_error :=
+endif
+
+# -----------------------------------------------------------------------------
+# Function : gdk_log
+# Arguments: 1: text to print when GDK_LOG is defined
+# Returns : None
+# Usage : $(call gdk_log,<some text>)
+# -----------------------------------------------------------------------------
+ifdef GDK_LOG
+gdk_log = $(info $(__gdk_name): $1)
+else
+gdk_log :=
+endif
+
+# ====================================================================
+#
+# Host system auto-detection.
+#
+# ====================================================================
+
+#
+# Determine host system and architecture from the environment
+#
+HOST_OS := $(strip $(HOST_OS))
+ifndef HOST_OS
+ # On all modern variants of Windows (including Cygwin and Wine)
+ # the OS environment variable is defined to 'Windows_NT'
+ #
+ # The value of PROCESSOR_ARCHITECTURE will be x86 or AMD64
+ #
+ ifeq ($(OS),Windows_NT)
+ HOST_OS := windows
+ else
+ # For other systems, use the `uname` output
+ UNAME := $(shell uname -s)
+ ifneq (,$(findstring Linux,$(UNAME)))
+ HOST_OS := linux
+ endif
+ ifneq (,$(findstring Darwin,$(UNAME)))
+ HOST_OS := darwin
+ endif
+ # We should not be there, but just in case !
+ ifneq (,$(findstring CYGWIN,$(UNAME)))
+ HOST_OS := windows
+ endif
+ ifeq ($(HOST_OS),)
+ $(call __gdk_info,Unable to determine HOST_OS from uname -s: $(UNAME))
+ $(call __gdk_info,Please define HOST_OS in your environment.)
+ $(call __gdk_error,Aborting.)
+ endif
+ endif
+ $(call gdk_log,Host OS was auto-detected: $(HOST_OS))
+else
+ $(call gdk_log,Host OS from environment: $(HOST_OS))
+endif
+
+HOST_ARCH := $(strip $(HOST_ARCH))
+ifndef HOST_ARCH
+ ifeq ($(HOST_OS),windows)
+ HOST_ARCH := $(PROCESSOR_ARCHITECTURE)
+ ifeq ($(HOST_ARCH),AMD64)
+ HOST_ARCH := x86
+ endif
+ else # HOST_OS != windows
+ UNAME := $(shell uname -m)
+ ifneq (,$(findstring 86,$(UNAME)))
+ HOST_ARCH := x86
+ endif
+ # We should probably should not care at all
+ ifneq (,$(findstring Power,$(UNAME)))
+ HOST_ARCH := ppc
+ endif
+ ifeq ($(HOST_ARCH),)
+ $(call __gdk_info,Unsupported host architecture: $(UNAME))
+ $(call __gdk_error,Aborting)
+ endif
+ endif # HOST_OS != windows
+ $(call gdk_log,Host CPU was auto-detected: $(HOST_ARCH))
+else
+ $(call gdk_log,Host CPU from environment: $(HOST_ARCH))
+endif
+
+HOST_TAG := $(HOST_OS)-$(HOST_ARCH)
+
+# The directory separator used on this host
+HOST_DIRSEP := :
+
+# For now always use ":" since Windows is Cygwin
+#ifeq ($(HOST_OS),windows)
+# HOST_DIRSEP := ;
+#endif
+
+# If we are on Windows, we need to check that we are not running
+# Cygwin 1.5, which is deprecated and won't run our toolchain
+# binaries properly.
+#
+ifeq ($(HOST_TAG),windows-x86)
+ # On cygwin, 'uname -r' returns something like 1.5.23(0.225/5/3)
+ # We recognize 1.5. as the prefix to look for then.
+ CYGWIN_VERSION := $(shell uname -r)
+ ifneq ($(filter XX1.5.%,XX$(CYGWIN_VERSION)),)
+ $(call __gdk_info,You seem to be running Cygwin 1.5, which is not supported.)
+ $(call __gdk_info,Please upgrade to Cygwin 1.7 or higher.)
+ $(call __gdk_error,Aborting.)
+ endif
+ # special-case the host-tag
+ HOST_TAG := windows
+endif
+$(call gdk_log,HOST_TAG set to $(HOST_TAG))
+
+#
+# Verify that the 'awk' tool has the features we need.
+# Both Nawk and Gawk do.
+#
+HOST_AWK := $(strip $(HOST_AWK))
+ifndef HOST_AWK
+ HOST_AWK := awk
+ $(call gdk_log,Host awk tool was auto-detected: $(HOST_AWK))
+else
+ $(call gdk_log,Host awk tool from environment: $(HOST_AWK))
+endif
+
+# Location of all awk scripts we use
+BUILD_AWK := $(GDK_ROOT)/build/awk
+
+AWK_TEST := $(shell $(HOST_AWK) -f $(BUILD_AWK)/check-awk.awk)
+$(call gdk_log,Host awk test returned: $(AWK_TEST))
+ifneq ($(AWK_TEST),Pass)
+ $(call __gdk_info,Host awk tool is outdated. Please define HOST_AWK to point to Gawk or Nawk !)
+ $(call __gdk_error,Aborting.)
+endif
+
+#
+# On windows, define the 'cygwin-to-host-path' function here depending on the
+# environment. The rules are the following:
+#
+# 1/ If "cygpath' is not in your path, do not use it at all. It looks like
+# this allows to build with the GDK from MSys without problems.
+#
+# 2/ Since invoking 'cygpath -m' from GNU Make for each source file is
+# _very_ slow, try to generate a Make function that performs the mapping
+# from cygwin to host paths through simple substitutions.
+#
+# 3/ In case we fail horribly, allow the user to define GDK_USE_CYGPATH to '1'
+# in order to use 'cygpath -m' nonetheless. This is only a backup plan in
+# case our automatic substitution function doesn't work (only likely if you
+# have a very weird cygwin setup).
+#
+# The function for 2/ is generated by an awk script. It's really a series
+# of nested patsubst calls, that look like:
+#
+# cygwin-to-host-path = $(patsubst /cygdrive/c/%,c:/%,\
+# $(patsusbt /cygdrive/d/%,d:/%, \
+# $1)
+#
+# except that the actual definition is built from the list of mounted
+# drives as reported by "mount" and deals with drive letter cases (i.e.
+# '/cygdrive/c' and '/cygdrive/C')
+#
+ifeq ($(HOST_OS),windows)
+ CYGPATH := $(strip $(HOST_CYGPATH))
+ ifndef CYGPATH
+ $(call gdk_log, Probing for 'cygpath' program)
+ CYGPATH := $(strip $(shell which cygpath 2>/dev/null))
+ ifndef CYGPATH
+ $(call gdk_log, 'cygpath' was *not* found in your path)
+ else
+ $(call gdk_log, 'cygpath' found as: $(CYGPATH))
+ endif
+ endif
+ ifndef CYGPATH
+ cygwin-to-host-path = $1
+ else
+ ifeq ($(GDK_USE_CYGPATH),1)
+ $(call gdk_log, Forced usage of 'cygpath -m' through GDK_USE_CYGPATH=1)
+ cygwin-to-host-path = $(strip $(shell $(CYGPATH) -m $1))
+ else
+ # Call an awk script to generate a Makefile fragment used to define a function
+ WINDOWS_HOST_PATH_FRAGMENT := $(shell mount | $(HOST_AWK) -f $(BUILD_AWK)/gen-windows-host-path.awk)
+ ifeq ($(GDK_LOG),1)
+ $(info Using cygwin substitution rules:)
+ $(eval $(shell mount | $(HOST_AWK) -f $(BUILD_AWK)/gen-windows-host-path.awk -vVERBOSE=1))
+ endif
+ $(eval cygwin-to-host-path = $(WINDOWS_HOST_PATH_FRAGMENT))
+ endif
+ endif
+endif # HOST_OS == windows
+
+# The location of the build system files
+BUILD_SYSTEM := $(GDK_ROOT)/build/core
+
+# Include common definitions
+include $(BUILD_SYSTEM)/definitions.mk
+
+# ====================================================================
+#
+# Read all toolchain-specific configuration files.
+#
+# Each toolchain must have a corresponding config.mk file located
+# in build/toolchains/<name>/ that will be included here.
+#
+# Each one of these files should define the following variables:
+# TOOLCHAIN_NAME toolchain name (e.g. arm-eabi-4.2.1)
+# TOOLCHAIN_ABIS list of target ABIs supported by the toolchain.
+#
+# Then, it should include $(ADD_TOOLCHAIN) which will perform
+# book-keeping for the build system.
+#
+# ====================================================================
+
+# the build script to include in each toolchain config.mk
+ADD_TOOLCHAIN := $(BUILD_SYSTEM)/add-toolchain.mk
+
+# the list of all toolchains in this GDK
+GDK_ALL_TOOLCHAINS :=
+GDK_ALL_ABIS :=
+
+TOOLCHAIN_CONFIGS := $(wildcard $(GDK_ROOT)/toolchains/*/config.mk)
+$(foreach _config_mk,$(TOOLCHAIN_CONFIGS),\
+ $(eval include $(BUILD_SYSTEM)/add-toolchain.mk)\
+)
+
+GDK_ALL_TOOLCHAINS := $(call remove-duplicates,$(GDK_ALL_TOOLCHAINS))
+GDK_ALL_ABIS := $(call remove-duplicates,$(GDK_ALL_ABIS))
+
+# The default toolchain is now arm-eabi-4.4.0, however its
+# C++ compiler is a tad bit more pedantic with certain
+# constructs (e.g. templates) so allow users to switch back
+# to the old 4.2.1 instead if they really want to.
+#
+# NOTE: you won't get armeabi-v7a support though !
+#
+GDK_TOOLCHAIN := $(strip $(GDK_TOOLCHAIN))
+ifdef GDK_TOOLCHAIN
+ # check that the toolchain name is supported
+ $(if $(filter-out $(GDK_ALL_TOOLCHAINS),$(GDK_TOOLCHAIN)),\
+ $(call __gdk_info,GDK_TOOLCHAIN is defined to the unsupported value $(GDK_TOOLCHAIN)) \
+ $(call __gdk_info,Please use one of the following values: $(GDK_ALL_TOOLCHAINS))\
+ $(call __gdk_error,Aborting)\
+ ,)
+ $(call gdk_log, Using specific toolchain $(GDK_TOOLCHAIN))
+endif
+
+$(call gdk_log, This GDK supports the following toolchains and target ABIs:)
+$(foreach tc,$(GDK_ALL_TOOLCHAINS),\
+ $(call gdk_log, $(space)$(space)$(tc): $(GDK_TOOLCHAIN.$(tc).abis))\
+)
+
+# ====================================================================
+#
+# Read all platform-specific configuration files.
+#
+# Each platform must be located in build/platforms/android-<apilevel>
+# where <apilevel> corresponds to an API level number, with:
+# 3 -> Android 1.5
+# 4 -> next platform release
+#
+# ====================================================================
+
+# The platform files were moved in the Android source tree from
+# $TOP/gdk/build/platforms to $TOP/development/gdk/platforms. However,
+# the official GDK release packages still place them under the old
+# location for now, so deal with this here
+#
+GDK_PLATFORMS_ROOT := $(strip $(GDK_PLATFORMS_ROOT))
+ifndef GDK_PLATFORMS_ROOT
+ GDK_PLATFORMS_ROOT := $(strip $(wildcard $(GDK_ROOT)/platforms))
+ ifndef GDK_PLATFORMS_ROOT
+ GDK_PLATFORMS_ROOT := $(strip $(wildcard $(GDK_ROOT)/build/platforms))
+ endif
+
+ ifndef GDK_PLATFORMS_ROOT
+ $(call __gdk_info,Could not find platform files (headers and libraries))
+ $(if $(strip $(wildcard $(GDK_ROOT)/RELEASE.TXT)),\
+ $(call __gdk_info,Please define GDK_PLATFORMS_ROOT to point to a valid directory.)\
+ ,\
+ $(call __gdk_info,Please run build/tools/build-platforms.sh to build the corresponding directory.)\
+ )
+ $(call __gdk_error,Aborting)
+ endif
+
+ $(call gdk_log,Found platform root directory: $(GDK_PLATFORMS_ROOT))
+endif
+ifeq ($(strip $(wildcard $(GDK_PLATFORMS_ROOT)/android-*)),)
+ $(call __gdk_info,Your GDK_PLATFORMS_ROOT points to an invalid directory)
+ $(call __gdk_info,Current value: $(GDK_PLATFORMS_ROOT))
+ $(call __gdk_error,Aborting)
+endif
+
+GDK_ALL_PLATFORMS := $(strip $(notdir $(wildcard $(GDK_PLATFORMS_ROOT)/android-*)))
+$(call gdk_log,Found supported platforms: $(GDK_ALL_PLATFORMS))
+
+$(foreach _platform,$(GDK_ALL_PLATFORMS),\
+ $(eval include $(BUILD_SYSTEM)/add-platform.mk)\
+)
diff --git a/build/core/main.mk b/build/core/main.mk
new file mode 100644
index 0000000..45fdbd7
--- /dev/null
+++ b/build/core/main.mk
@@ -0,0 +1,138 @@
+# Copyright (C) 2009 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 the main configuration variables, and read the host-specific
+# configuration file that is normally generated by build/host-setup.sh
+#
+# ====================================================================
+
+# Detect the NDK installation path by processing this Makefile's location.
+# This assumes we are located under $NDK_ROOT/build/core/main.mk
+#
+NDK_ROOT := $(lastword $(MAKEFILE_LIST))
+NDK_ROOT := $(strip $(NDK_ROOT:%build/core/main.mk=%))
+ifeq ($(NDK_ROOT),)
+ # for the case when we're invoked from the NDK install path
+ NDK_ROOT := .
+else
+ # get rid of trailing slash
+ NDK_ROOT := $(NDK_ROOT:%/=%)
+endif
+ifdef NDK_LOG
+ $(info Android NDK: NDK installation path auto-detected: '$(NDK_ROOT)')
+endif
+
+include $(NDK_ROOT)/build/core/init.mk
+
+# ====================================================================
+#
+# Read all application configuration files
+#
+# Each 'application' must have a corresponding Application.mk file
+# located in apps/<name> where <name> is a liberal name that doesn't
+# contain any space in it, used to uniquely identify the
+#
+# See docs/ANDROID-MK.TXT for their specification.
+#
+# ====================================================================
+
+NDK_ALL_APPS :=
+NDK_APPS_ROOT := $(NDK_ROOT)/apps
+
+# Get the list of apps listed under apps/*
+NDK_APPLICATIONS := $(wildcard $(NDK_APPS_ROOT)/*)
+NDK_ALL_APPS := $(NDK_APPLICATIONS:$(NDK_APPS_ROOT)/%=%)
+
+# Check that APP is not empty
+APP := $(strip $(APP))
+ifndef APP
+ $(call __ndk_info,\
+ The APP variable is undefined or empty.)
+ $(call __ndk_info,\
+ Please define it to one of: $(NDK_ALL_APPS))
+ $(call __ndk_info,\
+ You can also add new applications by writing an Application.mk file.)
+ $(call __ndk_info,\
+ See docs/APPLICATION-MK.TXT for details.)
+ $(call __ndk_error, Aborting)
+endif
+
+# Check that all apps listed in APP do exist
+_bad_apps := $(strip $(filter-out $(NDK_ALL_APPS),$(APP)))
+ifdef _bad_apps
+ $(call __ndk_info,\
+ APP variable defined to unknown applications: $(_bad_apps))
+ $(call __ndk_info,\
+ You might want to use one of the following: $(NDK_ALL_APPS))
+ $(call __ndk_error, Aborting)
+endif
+
+# Check that all apps listed in APP have an Application.mk
+
+$(foreach _app,$(APP),\
+ $(eval _application_mk := $(strip $(wildcard $(NDK_ROOT)/apps/$(_app)/Application.mk))) \
+ $(call ndk_log,Parsing $(_application_mk))\
+ $(if $(_application_mk),\
+ $(eval include $(BUILD_SYSTEM)/add-application.mk)\
+ ,\
+ $(call __ndk_info,\
+ Missing file: apps/$(_app)/Application.mk !)\
+ $(call __ndk_error, Aborting)\
+ )\
+)
+
+# clean up environment, just to be safe
+$(call clear-vars, $(NDK_APP_VARS))
+
+ifeq ($(strip $(NDK_ALL_APPS)),)
+ $(call __ndk_info,\
+ The NDK could not find a proper application description under apps/*/Application.mk)
+ $(call __ndk_info,\
+ Please follow the instructions in docs/NDK-APPS.TXT to write one.)
+ $(call __ndk_error, Aborting)
+endif
+
+# now check that APP doesn't contain an unknown app name
+# if it does, we ignore them if there is at least one known
+# app name in the list. Otherwise, abort with an error message
+#
+_unknown_apps := $(filter-out $(NDK_ALL_APPS),$(APP))
+_known_apps := $(filter $(NDK_ALL_APPS),$(APP))
+
+NDK_APPS := $(APP)
+
+$(if $(_unknown_apps),\
+ $(if $(_known_apps),\
+ $(call __ndk_info,WARNING:\
+ Removing unknown names from APP variable: $(_unknown_apps))\
+ $(eval NDK_APPS := $(_known_apps))\
+ ,\
+ $(call __ndk_info,\
+ The APP variable contains unknown app names: $(_unknown_apps))\
+ $(call __ndk_info,\
+ Please use one of: $(NDK_ALL_APPS))\
+ $(call __ndk_error, Aborting)\
+ )\
+)
+
+$(call __ndk_info,Building for application '$(NDK_APPS)')
+
+# Where all app-specific generated files will be stored
+NDK_APP_OUT := $(NDK_ROOT)/out/apps
+
+include $(BUILD_SYSTEM)/setup-imports.mk
+include $(BUILD_SYSTEM)/build-all.mk
diff --git a/build/core/ndk-common.sh b/build/core/ndk-common.sh
new file mode 100644
index 0000000..f349ff2
--- /dev/null
+++ b/build/core/ndk-common.sh
@@ -0,0 +1,728 @@
+# Copyright (C) 2009 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.
+#
+
+# A collection of shell function definitions used by various build scripts
+# in the Android NDK (Native Development Kit)
+#
+
+# Get current script name into PROGNAME
+PROGNAME=`basename $0`
+
+# Find the Android NDK root, assuming we are invoked from a script
+# within its directory structure.
+#
+# $1: Variable name that will receive the path
+# $2: Path of invoking script
+find_ndk_root ()
+{
+ # Try to auto-detect the NDK root by walking up the directory
+ # path to the current script.
+ local PROGDIR="`dirname \"$2\"`"
+ while [ -n "1" ] ; do
+ if [ -d "$PROGDIR/build/core" ] ; then
+ break
+ fi
+ if [ -z "$PROGDIR" -o "$PROGDIR" = '/' ] ; then
+ return 1
+ fi
+ PROGDIR="`cd \"$PROGDIR/..\" && pwd`"
+ done
+ eval $1="$PROGDIR"
+}
+
+# Put location of Android NDK into ANDROID_NDK_ROOT and
+# perform a tiny amount of sanity check
+#
+if [ -z "$ANDROID_NDK_ROOT" ] ; then
+ find_ndk_root ANDROID_NDK_ROOT "$0"
+ if [ $? != 0 ]; then
+ echo "Please define ANDROID_NDK_ROOT to point to the root of your"
+ echo "Android NDK installation."
+ exit 1
+ fi
+fi
+
+echo "$ANDROID_NDK_ROOT" | grep -q -e " "
+if [ $? = 0 ] ; then
+ echo "ERROR: The Android NDK installation path contains a space !"
+ echo "Please install to a different location."
+ exit 1
+fi
+
+if [ ! -d $ANDROID_NDK_ROOT ] ; then
+ echo "ERROR: Your ANDROID_NDK_ROOT variable does not point to a directory."
+ exit 1
+fi
+
+if [ ! -f $ANDROID_NDK_ROOT/build/core/ndk-common.sh ] ; then
+ echo "ERROR: Your ANDROID_NDK_ROOT variable does not point to a valid directory."
+ exit 1
+fi
+
+## Logging support
+##
+VERBOSE=${VERBOSE-yes}
+VERBOSE2=${VERBOSE2-no}
+
+
+# If NDK_LOGFILE is defined in the environment, use this as the log file
+TMPLOG=
+if [ -n "$NDK_LOGFILE" ] ; then
+ mkdir -p `dirname "$NDK_LOGFILE"` && touch "$NDK_LOGFILE"
+ TMPLOG="$NDK_LOGFILE"
+fi
+
+# Setup a log file where all log() and log2() output will be sent
+#
+# $1: log file path (optional)
+#
+setup_default_log_file ()
+{
+ if [ -n "$NDK_LOGFILE" ] ; then
+ return
+ fi
+ if [ -n "$1" ] ; then
+ NDK_LOGFILE="$1"
+ else
+ NDK_LOGFILE=/tmp/ndk-log-$$.txt
+ fi
+ export NDK_LOGFILE
+ TMPLOG="$NDK_LOGFILE"
+ rm -rf "$TMPLOG" && mkdir -p `dirname "$TMPLOG"` && touch "$TMPLOG"
+ echo "To follow build in another terminal, please use: tail -F $TMPLOG"
+}
+
+dump ()
+{
+ if [ -n "$TMPLOG" ] ; then
+ echo "$@" >> $TMPLOG
+ fi
+ echo "$@"
+}
+
+log ()
+{
+ if [ "$VERBOSE" = "yes" ] ; then
+ echo "$@"
+ else
+ if [ -n "$TMPLOG" ] ; then
+ echo "$@" >> $TMPLOG
+ fi
+ fi
+}
+
+log2 ()
+{
+ if [ "$VERBOSE2" = "yes" ] ; then
+ echo "$@"
+ else
+ if [ -n "$TMPLOG" ] ; then
+ echo "$@" >> $TMPLOG
+ fi
+ fi
+}
+
+run ()
+{
+ if [ "$VERBOSE" = "yes" ] ; then
+ echo "## COMMAND: $@"
+ $@ 2>&1
+ else
+ if [ -n "$TMPLOG" ] ; then
+ echo "## COMMAND: $@" >> $TMPLOG
+ $@ >>$TMPLOG 2>&1
+ else
+ $@ > /dev/null 2>&1
+ fi
+ fi
+}
+
+panic ()
+{
+ dump "ERROR: $@"
+ exit 1
+}
+
+fail_panic ()
+{
+ if [ $? != 0 ] ; then
+ dump "ERROR: $@"
+ exit 1
+ fi
+}
+
+
+## Utilities
+##
+
+# Return the value of a given named variable
+# $1: variable name
+#
+# example:
+# FOO=BAR
+# BAR=ZOO
+# echo `var_value $FOO`
+# will print 'ZOO'
+#
+var_value ()
+{
+ # find a better way to do that ?
+ eval echo "$`echo $1`"
+}
+
+# convert to uppercase
+# assumes tr is installed on the platform ?
+#
+to_uppercase ()
+{
+ echo $1 | tr "[:lower:]" "[:upper:]"
+}
+
+## Normalize OS and CPU
+##
+HOST_ARCH=`uname -m`
+case "$HOST_ARCH" in
+ i?86) HOST_ARCH=x86
+ ;;
+ amd64) HOST_ARCH=x86_64
+ ;;
+ powerpc) HOST_ARCH=ppc
+ ;;
+esac
+
+log2 "HOST_ARCH=$HOST_ARCH"
+
+# at this point, the supported values for CPU are:
+# x86
+# x86_64
+# ppc
+#
+# other values may be possible but haven't been tested
+#
+HOST_EXE=""
+HOST_OS=`uname -s`
+case "$HOST_OS" in
+ Darwin)
+ HOST_OS=darwin
+ ;;
+ Linux)
+ # note that building 32-bit binaries on x86_64 is handled later
+ HOST_OS=linux
+ ;;
+ FreeBsd) # note: this is not tested
+ HOST_OS=freebsd
+ ;;
+ CYGWIN*|*_NT-*)
+ HOST_OS=windows
+ HOST_EXE=.exe
+ if [ "x$OSTYPE" = xcygwin ] ; then
+ HOST_OS=cygwin
+ fi
+ ;;
+esac
+
+log2 "HOST_OS=$HOST_OS"
+log2 "HOST_EXE=$HOST_EXE"
+
+# at this point, the value of HOST_OS should be one of the following:
+# linux
+# darwin
+# windows (MSys)
+# cygwin
+#
+# Note that cygwin is treated as a special case because it behaves very differently
+# for a few things. Other values may be possible but have not been tested
+#
+
+# define HOST_TAG as a unique tag used to identify both the host OS and CPU
+# supported values are:
+#
+# linux-x86
+# linux-x86_64
+# darwin-x86
+# darwin-ppc
+# windows
+#
+# other values are possible but were not tested.
+#
+compute_host_tag ()
+{
+ case "$HOST_OS" in
+ windows|cygwin)
+ HOST_TAG="windows"
+ ;;
+ *) HOST_TAG="${HOST_OS}-${HOST_ARCH}"
+ esac
+ log2 "HOST_TAG=$HOST_TAG"
+}
+
+compute_host_tag
+
+# Compute the number of host CPU cores an HOST_NUM_CPUS
+#
+case "$HOST_OS" in
+ linux)
+ HOST_NUM_CPUS=`cat /proc/cpuinfo | grep processor | wc -l`
+ ;;
+ darwin|freebsd)
+ HOST_NUM_CPUS=`sysctl -n hw.ncpu`
+ ;;
+ windows|cygwin)
+ HOST_NUM_CPUS=$NUMBER_OF_PROCESSORS
+ ;;
+ *) # let's play safe here
+ HOST_NUM_CPUS=1
+esac
+
+log2 "HOST_NUM_CPUS=$HOST_NUM_CPUS"
+
+# If BUILD_NUM_CPUS is not already defined in your environment,
+# define it as the double of HOST_NUM_CPUS. This is used to
+# run Make commands in parralles, as in 'make -j$BUILD_NUM_CPUS'
+#
+if [ -z "$BUILD_NUM_CPUS" ] ; then
+ BUILD_NUM_CPUS=`expr $HOST_NUM_CPUS \* 2`
+fi
+
+log2 "BUILD_NUM_CPUS=$BUILD_NUM_CPUS"
+
+
+## HOST TOOLCHAIN SUPPORT
+##
+
+# force the generation of 32-bit binaries on 64-bit systems
+#
+FORCE_32BIT=no
+force_32bit_binaries ()
+{
+ if [ "$HOST_ARCH" = x86_64 ] ; then
+ log2 "Forcing generation of 32-bit host binaries on $HOST_ARCH"
+ FORCE_32BIT=yes
+ HOST_ARCH=x86
+ log2 "HOST_ARCH=$HOST_ARCH"
+ compute_host_tag
+ fi
+}
+
+# On Windows, cygwin binaries will be generated by default, but
+# you can force mingw ones that do not link to cygwin.dll if you
+# call this function.
+#
+disable_cygwin ()
+{
+ if [ $OS = cygwin ] ; then
+ log2 "Disabling cygwin binaries generation"
+ CFLAGS="$CFLAGS -mno-cygwin"
+ LDFLAGS="$LDFLAGS -mno-cygwin"
+ OS=windows
+ HOST_OS=windows
+ compute_host_tag
+ fi
+}
+
+# Various probes are going to need to run a small C program
+mkdir -p /tmp/ndk-$USER/tmp/tests
+
+TMPC=/tmp/ndk-$USER/tmp/tests/test-$$.c
+TMPO=/tmp/ndk-$USER/tmp/tests/test-$$.o
+TMPE=/tmp/ndk-$USER/tmp/tests/test-$$$EXE
+TMPL=/tmp/ndk-$USER/tmp/tests/test-$$.log
+
+# cleanup temporary files
+clean_temp ()
+{
+ rm -f $TMPC $TMPO $TMPL $TMPE
+}
+
+# cleanup temp files then exit with an error
+clean_exit ()
+{
+ clean_temp
+ exit 1
+}
+
+# this function will setup the compiler and linker and check that they work as advertised
+# note that you should call 'force_32bit_binaries' before this one if you want it to
+# generate 32-bit binaries on 64-bit systems (that support it).
+#
+setup_toolchain ()
+{
+ if [ -z "$CC" ] ; then
+ CC=gcc
+ fi
+ if [ -z "$CXX" ] ; then
+ CXX=g++
+ fi
+ if [ -z "$CXXFLAGS" ] ; then
+ CXXFLAGS="$CFLAGS"
+ fi
+ if [ -z "$LD" ] ; then
+ LD="$CC"
+ fi
+
+ log2 "Using '$CC' as the C compiler"
+
+ # check that we can compile a trivial C program with this compiler
+ mkdir -p $(dirname "$TMPC")
+ cat > $TMPC <<EOF
+int main(void) {}
+EOF
+
+ if [ "$FORCE_32BIT" = yes ] ; then
+ CC="$CC -m32"
+ CXX="$CXX -m32"
+ LD="$LD -m32"
+ compile
+ if [ $? != 0 ] ; then
+ # sometimes, we need to also tell the assembler to generate 32-bit binaries
+ # this is highly dependent on your GCC installation (and no, we can't set
+ # this flag all the time)
+ CFLAGS="$CFLAGS -Wa,--32"
+ compile
+ fi
+ fi
+
+ compile
+ if [ $? != 0 ] ; then
+ echo "your C compiler doesn't seem to work:"
+ cat $TMPL
+ clean_exit
+ fi
+ log "CC : compiler check ok ($CC)"
+
+ # check that we can link the trivial program into an executable
+ link
+ if [ $? != 0 ] ; then
+ OLD_LD="$LD"
+ LD="$CC"
+ compile
+ link
+ if [ $? != 0 ] ; then
+ LD="$OLD_LD"
+ echo "your linker doesn't seem to work:"
+ cat $TMPL
+ clean_exit
+ fi
+ fi
+ log2 "Using '$LD' as the linker"
+ log "LD : linker check ok ($LD)"
+
+ # check the C++ compiler
+ log2 "Using '$CXX' as the C++ compiler"
+
+ cat > $TMPC <<EOF
+#include <iostream>
+using namespace std;
+int main()
+{
+ cout << "Hello World!" << endl;
+ return 0;
+}
+EOF
+
+ compile_cpp
+ if [ $? != 0 ] ; then
+ echo "your C++ compiler doesn't seem to work"
+ cat $TMPL
+ clean_exit
+ fi
+
+ log "CXX : C++ compiler check ok ($CXX)"
+
+ # XXX: TODO perform AR checks
+ AR=ar
+ ARFLAGS=
+}
+
+# try to compile the current source file in $TMPC into an object
+# stores the error log into $TMPL
+#
+compile ()
+{
+ log2 "Object : $CC -o $TMPO -c $CFLAGS $TMPC"
+ $CC -o $TMPO -c $CFLAGS $TMPC 2> $TMPL
+}
+
+compile_cpp ()
+{
+ log2 "Object : $CXX -o $TMPO -c $CXXFLAGS $TMPC"
+ $CXX -o $TMPO -c $CXXFLAGS $TMPC 2> $TMPL
+}
+
+# try to link the recently built file into an executable. error log in $TMPL
+#
+link()
+{
+ log2 "Link : $LD -o $TMPE $TMPO $LDFLAGS"
+ $LD -o $TMPE $TMPO $LDFLAGS 2> $TMPL
+}
+
+# run a command
+#
+execute()
+{
+ log2 "Running: $*"
+ $*
+}
+
+# perform a simple compile / link / run of the source file in $TMPC
+compile_exec_run()
+{
+ log2 "RunExec : $CC -o $TMPE $CFLAGS $TMPC"
+ compile
+ if [ $? != 0 ] ; then
+ echo "Failure to compile test program"
+ cat $TMPC
+ cat $TMPL
+ clean_exit
+ fi
+ link
+ if [ $? != 0 ] ; then
+ echo "Failure to link test program"
+ cat $TMPC
+ echo "------"
+ cat $TMPL
+ clean_exit
+ fi
+ $TMPE
+}
+
+pattern_match ()
+{
+ echo "$2" | grep -q -E -e "$1"
+}
+
+# Let's check that we have a working md5sum here
+check_md5sum ()
+{
+ A_MD5=`echo "A" | md5sum | cut -d' ' -f1`
+ if [ "$A_MD5" != "bf072e9119077b4e76437a93986787ef" ] ; then
+ echo "Please install md5sum on this machine"
+ exit 2
+ fi
+}
+
+# Find if a given shell program is available.
+# We need to take care of the fact that the 'which <foo>' command
+# may return either an empty string (Linux) or something like
+# "no <foo> in ..." (Darwin). Also, we need to redirect stderr
+# to /dev/null for Cygwin
+#
+# $1: variable name
+# $2: program name
+#
+# Result: set $1 to the full path of the corresponding command
+# or to the empty/undefined string if not available
+#
+find_program ()
+{
+ local PROG
+ PROG=`which $2 2>/dev/null`
+ if [ -n "$PROG" ] ; then
+ if pattern_match '^no ' "$PROG"; then
+ PROG=
+ fi
+ fi
+ eval $1="$PROG"
+}
+
+prepare_download ()
+{
+ find_program CMD_WGET wget
+ find_program CMD_CURL curl
+ find_program CMD_SCRP scp
+}
+
+# Download a file with either 'curl', 'wget' or 'scp'
+#
+# $1: source URL (e.g. http://foo.com, ssh://blah, /some/path)
+# $2: target file
+download_file ()
+{
+ # Is this HTTP, HTTPS or FTP ?
+ if pattern_match "^(http|https|ftp):.*" "$1"; then
+ if [ -n "$CMD_WGET" ] ; then
+ run $CMD_WGET -O $2 $1
+ elif [ -n "$CMD_CURL" ] ; then
+ run $CMD_CURL -o $2 $1
+ else
+ echo "Please install wget or curl on this machine"
+ exit 1
+ fi
+ return
+ fi
+
+ # Is this SSH ?
+ # Accept both ssh://<path> or <machine>:<path>
+ #
+ if pattern_match "^(ssh|[^:]+):.*" "$1"; then
+ if [ -n "$CMD_SCP" ] ; then
+ scp_src=`echo $1 | sed -e s%ssh://%%g`
+ run $CMD_SCP $scp_src $2
+ else
+ echo "Please install scp on this machine"
+ exit 1
+ fi
+ return
+ fi
+
+ # Is this a file copy ?
+ # Accept both file://<path> or /<path>
+ #
+ if pattern_match "^(file://|/).*" "$1"; then
+ cp_src=`echo $1 | sed -e s%^file://%%g`
+ run cp -f $cp_src $2
+ return
+ fi
+}
+
+
+# Unpack a given archive
+#
+# $1: archive file path
+# $2: optional target directory (current one if omitted)
+#
+unpack_archive ()
+{
+ local ARCHIVE="$1"
+ local DIR=${2-.}
+ local RESULT TARFLAGS ZIPFLAGS
+ mkdir -p "$DIR"
+ if [ "$VERBOSE2" = "yes" ] ; then
+ TARFLAGS="vxpf"
+ ZIPFLAGS=""
+ else
+ TARFLAGS="xpf"
+ ZIPFLAGS="q"
+ fi
+ case "$ARCHIVE" in
+ *.zip)
+ (cd $DIR && run unzip $ZIPFLAGS "$ARCHIVE")
+ ;;
+ *.tar)
+ run tar $TARFLAGS "$ARCHIVE" -C $DIR
+ ;;
+ *.tar.gz)
+ run tar z$TARFLAGS "$ARCHIVE" -C $DIR
+ ;;
+ *.tar.bz2)
+ run tar j$TARFLAGS "$ARCHIVE" -C $DIR
+ ;;
+ *)
+ panic "Cannot unpack archive with unknown extension: $ARCHIVE"
+ ;;
+ esac
+}
+
+# Pack a given archive
+#
+# $1: archive file path (including extension)
+# $2: source directory for archive content
+# $3+: list of files (including patterns), all if empty
+pack_archive ()
+{
+ local ARCHIVE="$1"
+ local SRCDIR="$2"
+ local SRCFILES
+ local TARFLAGS ZIPFLAGS
+ shift; shift;
+ if [ -z "$1" ] ; then
+ SRCFILES="*"
+ else
+ SRCFILES="$@"
+ fi
+ if [ "`basename $ARCHIVE`" = "$ARCHIVE" ] ; then
+ ARCHIVE="`pwd`/$ARCHIVE"
+ fi
+ mkdir -p `dirname $ARCHIVE`
+ if [ "$VERBOSE2" = "yes" ] ; then
+ TARFLAGS="vcf"
+ ZIPFLAGS="-9r"
+ else
+ TARFLAGS="cf"
+ ZIPFLAGS="-9qr"
+ fi
+ case "$ARCHIVE" in
+ *.zip)
+ (cd $SRCDIR && run zip $ZIPFLAGS "$ARCHIVE" $SRCFILES)
+ ;;
+ *.tar)
+ (cd $SRCDIR && run tar $TARFLAGS "$ARCHIVE" $SRCFILES)
+ ;;
+ *.tar.gz)
+ (cd $SRCDIR && run tar z$TARFLAGS "$ARCHIVE" $SRCFILES)
+ ;;
+ *.tar.bz2)
+ (cd $SRCDIR && run tar j$TARFLAGS "$ARCHIVE" $SRCFILES)
+ ;;
+ *)
+ panic "Unsupported archive format: $ARCHIVE"
+ ;;
+ esac
+}
+
+# Copy a directory, create target location if needed
+#
+# $1: source directory
+# $2: target directory location
+#
+copy_directory ()
+{
+ local SRCDIR="$1"
+ local DSTDIR="$2"
+ if [ ! -d "$SRCDIR" ] ; then
+ panic "Can't copy from non-directory: $SRCDIR"
+ fi
+ log "Copying directory: "
+ log " from $SRCDIR"
+ log " to $DSTDIR"
+ mkdir -p "$DSTDIR" && (cd "$SRCDIR" && tar cf - *) | (tar xf - -C "$DSTDIR")
+ fail_panic "Cannot copy to directory: $DSTDIR"
+}
+
+# This is the same than copy_directory(), but symlinks will be replaced
+# by the file they actually point to instead.
+copy_directory_nolinks ()
+{
+ local SRCDIR="$1"
+ local DSTDIR="$2"
+ if [ ! -d "$SRCDIR" ] ; then
+ panic "Can't copy from non-directory: $SRCDIR"
+ fi
+ log "Copying directory (without symlinks): "
+ log " from $SRCDIR"
+ log " to $DSTDIR"
+ mkdir -p "$DSTDIR" && (cd "$SRCDIR" && tar chf - *) | (tar xf - -C "$DSTDIR")
+ fail_panic "Cannot copy to directory: $DSTDIR"
+}
+
+# Copy certain files from one directory to another one
+# $1: source directory
+# $2: target directory
+# $3+: file list (including patterns)
+copy_file_list ()
+{
+ local SRCDIR="$1"
+ local DSTDIR="$2"
+ shift; shift;
+ if [ ! -d "$SRCDIR" ] ; then
+ panic "Cant' copy from non-directory: $SRCDIR"
+ fi
+ log "Copying file: $@"
+ log " from $SRCDIR"
+ log " to $DSTDIR"
+ mkdir -p "$DSTDIR" && (cd "$SRCDIR" && tar cf - $@) | (tar xf - -C "$DSTDIR")
+ fail_panic "Cannot copy files to directory: $DSTDIR"
+}
diff --git a/build/core/prebuilt-library.mk b/build/core/prebuilt-library.mk
new file mode 100644
index 0000000..76999ef
--- /dev/null
+++ b/build/core/prebuilt-library.mk
@@ -0,0 +1,66 @@
+# Copyright (C) 2010 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.
+#
+
+# this file is included from prebuilt-shared-library.mk or
+# prebuilt-static-library.mk to declare prebuilt library binaries.
+#
+
+$(call assert-defined, LOCAL_BUILD_SCRIPT LOCAL_MAKEFILE LOCAL_PREBUILT_PREFIX LOCAL_PREBUILT_SUFFIX)
+
+$(call check-defined-LOCAL_MODULE,$(LOCAL_BUILD_SCRIPT))
+$(call check-LOCAL_MODULE,$(LOCAL_MAKEFILE))
+$(call check-LOCAL_MODULE_FILENAME)
+
+# Check that LOCAL_SRC_FILES contains only paths to shared libraries
+ifneq ($(words $(LOCAL_SRC_FILES)),1)
+$(call __ndk_info,ERROR:$(LOCAL_MAKEFILE):$(LOCAL_MODULE): The LOCAL_SRC_FILES for a prebuilt static library should only contain one item))
+$(call __ndk_error,Aborting)
+endif
+
+bad_prebuilts := $(filter-out %$(LOCAL_PREBUILT_SUFFIX),$(LOCAL_SRC_FILES))
+ifdef bad_prebuilts
+$(call __ndk_info,ERROR:$(LOCAL_MAKEFILE):$(LOCAL_MODULE): LOCAL_SRC_FILES should point to a file ending with "$(LOCAL_PREBUILT_SUFFIX)")
+$(call __ndk_info,The following file is unsupported: $(bad_prebuilts))
+$(call __ndk_error,Aborting)
+endif
+
+prebuilt := $(strip $(wildcard $(LOCAL_PATH)/$(LOCAL_SRC_FILES)))
+ifndef prebuilt
+$(call __ndk_info,ERROR:$(LOCAL_MAKEFILE):$(LOCAL_MODULE): LOCAL_SRC_FILES points to a missing file)
+$(call __ndk_info,Check that $(LOCAL_PATH)/$(LOCAL_SRC_FILES) exists, or that its path is correct)
+$(call __ndk_error,Aborting)
+endif
+
+# If LOCAL_MODULE_FILENAME is defined, it will be used to name the file
+# in the TARGET_OUT directory, and then the installation one. Note that
+# if shouldn't have an .a or .so extension nor contain directory separators.
+#
+# If the variable is not defined, we determine its value from LOCAL_SRC_FILES
+#
+LOCAL_MODULE_FILENAME := $(strip $(LOCAL_MODULE_FILENAME))
+ifndef LOCAL_MODULE_FILENAME
+ LOCAL_MODULE_FILENAME := $(notdir $(LOCAL_SRC_FILES))
+ LOCAL_MODULE_FILENAME := $(LOCAL_MODULE_FILENAME:%$(LOCAL_PREBUILT_SUFFIX)=%)
+endif
+$(eval $(call ev-check-module-filename))
+
+LOCAL_BUILT_MODULE := $(TARGET_OUT)/$(LOCAL_MODULE_FILENAME)$(LOCAL_PREBUILT_SUFFIX)
+LOCAL_OBJS_DIR := $(TARGET_OBJS)/$(LOCAL_MODULE)
+LOCAL_OBJECTS := $(prebuilt)
+LOCAL_SRC_FILES :=
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_OBJECTS)
+
+include $(BUILD_SYSTEM)/build-module.mk
diff --git a/build/core/prebuilt-shared-library.mk b/build/core/prebuilt-shared-library.mk
new file mode 100644
index 0000000..afe5e4b
--- /dev/null
+++ b/build/core/prebuilt-shared-library.mk
@@ -0,0 +1,27 @@
+# Copyright (C) 2010 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.
+#
+
+# this file is included from Android.mk files to build a target-specific
+# shared library
+#
+
+LOCAL_BUILD_SCRIPT := PREBUILT_SHARED_LIBRARY
+LOCAL_MODULE_CLASS := PREBUILT_SHARED_LIBRARY
+LOCAL_MAKEFILE := $(local-makefile)
+
+LOCAL_PREBUILT_PREFIX := lib
+LOCAL_PREBUILT_SUFFIX := .so
+
+include $(BUILD_SYSTEM)/prebuilt-library.mk
diff --git a/build/core/prebuilt-static-library.mk b/build/core/prebuilt-static-library.mk
new file mode 100644
index 0000000..69121ce
--- /dev/null
+++ b/build/core/prebuilt-static-library.mk
@@ -0,0 +1,27 @@
+# Copyright (C) 2010 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.
+#
+
+# this file is included from Android.mk files to build a target-specific
+# shared library
+#
+
+LOCAL_BUILD_SCRIPT := PREBUILT_STATIC_LIBRARY
+LOCAL_MODULE_CLASS := PREBUILT_STATIC_LIBRARY
+LOCAL_MAKEFILE := $(local-makefile)
+
+LOCAL_PREBUILT_PREFIX := lib
+LOCAL_PREBUILT_SUFFIX := .a
+
+include $(BUILD_SYSTEM)/prebuilt-library.mk
diff --git a/build/core/setup-abi.mk b/build/core/setup-abi.mk
new file mode 100644
index 0000000..74b317e
--- /dev/null
+++ b/build/core/setup-abi.mk
@@ -0,0 +1,37 @@
+# Copyright (C) 2009 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.
+#
+
+# this file is included multiple times by build/core/setup-app.mk
+#
+
+$(call gdk_log,Building application '$(GDK_APP_NAME)' for ABI '$(TARGET_ARCH_ABI)')
+
+# Map ABIs to a target architecture
+TARGET_ARCH_for_llvm := llvm
+
+TARGET_ARCH := $(TARGET_ARCH_for_$(TARGET_ARCH_ABI))
+
+TARGET_OUT := $(GDK_APP_OUT)/$(_app)/$(TARGET_ARCH_ABI)
+
+# Separate the debug and release objects. This prevents rebuilding
+# everything when you switch between these two modes. For projects
+# with lots of C++ sources, this can be a considerable time saver.
+ifeq ($(GDK_APP_OPTIM),debug)
+TARGET_OBJS := $(TARGET_OUT)/objs-debug
+else
+TARGET_OBJS := $(TARGET_OUT)/objs
+endif
+
+include $(BUILD_SYSTEM)/setup-toolchain.mk
diff --git a/build/core/setup-app.mk b/build/core/setup-app.mk
new file mode 100644
index 0000000..541040f
--- /dev/null
+++ b/build/core/setup-app.mk
@@ -0,0 +1,59 @@
+# Copyright (C) 2009 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.
+#
+
+# this file is included repeatedly from build/core/main.mk
+# and is used to prepare for app-specific build rules.
+#
+
+$(call assert-defined,_app)
+
+_map := GDK_APP.$(_app)
+
+# ok, let's parse all Android.mk source files in order to build
+# the modules for this app.
+#
+
+# Restore the APP_XXX variables just for this pass as GDK_APP_XXX
+#
+GDK_APP_NAME := $(_app)
+GDK_APP_APPLICATION_MK := $(call get,$(_map),Application.mk)
+
+$(foreach __name,$(GDK_APP_VARS),\
+ $(eval GDK_$(__name) := $(call get,$(_map),$(__name)))\
+)
+
+# make the application depend on the modules it requires
+.PHONY: gdk-app-$(_app)
+gdk-app-$(_app): $(GDK_APP_MODULES)
+all: gdk-app-$(_app)
+
+TARGET_PLATFORM := android-portable
+
+APP_ABI := $(strip $(GDK_APP_ABI))
+APP_ABI := llvm
+
+
+# Clear all installed binaries for this application
+# This ensures that if the build fails, you're not going to mistakenly
+# package an obsolete version of it. Or if you change the ABIs you're targetting,
+# you're not going to leave a stale shared library for the old one.
+#
+clean-installed-binaries::
+ $(hide) rm -f $(GDK_APP_PROJECT_PATH)/res/raw/lib*.bc
+
+$(foreach _abi,$(APP_ABI),\
+ $(eval TARGET_ARCH_ABI := $(_abi))\
+ $(eval include $(BUILD_SYSTEM)/setup-abi.mk) \
+)
diff --git a/build/core/setup-imports.mk b/build/core/setup-imports.mk
new file mode 100644
index 0000000..96fc1d5
--- /dev/null
+++ b/build/core/setup-imports.mk
@@ -0,0 +1,36 @@
+# Copyright (C) 2009-2010 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 the import path
+#
+# ====================================================================
+
+NDK_MODULE_PATH := $(strip $(NDK_MODULE_PATH))
+ifdef NDK_MODULE_PATH
+ ifneq ($(words $(NDK_MODULE_PATH)),1)
+ $(call __ndk_info,ERROR: You NDK_MODULE_PATH variable contains spaces)
+ $(call __ndk_info,Please fix the error and start again.)
+ $(call __ndk_error,Aborting)
+ endif
+endif
+
+$(call import-init)
+$(foreach __path,$(subst $(HOST_DIRSEP),$(space),$(NDK_MODULE_PATH)),\
+ $(call import-add-path,$(__path))\
+)
+$(call import-add-path-optional,$(NDK_ROOT)/sources)
+$(call import-add-path-optional,$(NDK_ROOT)/../development/ndk/sources)
diff --git a/build/core/setup-toolchain.mk b/build/core/setup-toolchain.mk
new file mode 100644
index 0000000..0cb68b1
--- /dev/null
+++ b/build/core/setup-toolchain.mk
@@ -0,0 +1,102 @@
+# Copyright (C) 2009 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.
+#
+
+# this file is included repeatedly from build/core/setup-abi.mk and is used
+# to setup the target toolchain for a given platform/abi combination.
+#
+
+$(call assert-defined,TARGET_PLATFORM TARGET_ARCH TARGET_ARCH_ABI)
+$(call assert-defined,GDK_APPS)
+
+# Check that we have a toolchain that supports the current ABI.
+# NOTE: If GDK_TOOLCHAIN is defined, we're going to use it.
+#
+ifndef GDK_TOOLCHAIN
+ TARGET_TOOLCHAIN_LIST := $(strip $(sort $(GDK_ABI.$(TARGET_ARCH_ABI).toolchains)))
+ ifndef TARGET_TOOLCHAIN_LIST
+ $(call __gdk_info,There is no toolchain that supports the $(TARGET_ARCH_ABI) ABI.)
+ $(call __gdk_info,Please modify the APP_ABI definition in $(GDK_APP_APPLICATION_MK) to use)
+ $(call __gdk_info,a set of the following values: $(GDK_ALL_ABIS))
+ $(call __gdk_error,Aborting)
+ endif
+ # Select the last toolchain from the sorted list.
+ # For now, this is enough to select armeabi-4.4.0 by default for ARM
+ TARGET_TOOLCHAIN := $(lastword $(TARGET_TOOLCHAIN_LIST))
+ $(call gdk_log,Using target toolchain '$(TARGET_TOOLCHAIN)' for '$(TARGET_ARCH_ABI)' ABI)
+else # GDK_TOOLCHAIN is not empty
+ TARGET_TOOLCHAIN_LIST := $(strip $(filter $(GDK_TOOLCHAIN),$(GDK_ABI.$(TARGET_ARCH_ABI).toolchains)))
+ ifndef TARGET_TOOLCHAIN_LIST
+ $(call __gdk_info,The selected toolchain ($(GDK_TOOLCHAIN)) does not support the $(TARGET_ARCH_ABI) ABI.)
+ $(call __gdk_info,Please modify the APP_ABI definition in $(GDK_APP_APPLICATION_MK) to use)
+ $(call __gdk_info,a set of the following values: $(GDK_TOOLCHAIN.$(GDK_TOOLCHAIN).abis))
+ $(call __gdk_info,Or change your GDK_TOOLCHAIN definition.)
+ $(call __gdk_error,Aborting)
+ endif
+ TARGET_TOOLCHAIN := $(GDK_TOOLCHAIN)
+endif # GDK_TOOLCHAIN is not empty
+
+TARGET_ABI := $(TARGET_PLATFORM)-$(TARGET_ARCH_ABI)
+
+# setup sysroot-related variables. The SYSROOT point to a directory
+# that contains all public header files for a given platform, plus
+# some libraries and object files used for linking the generated
+# target files properly.
+#
+SYSROOT := $(GDK_PLATFORMS_ROOT)/$(TARGET_PLATFORM)/arch-$(TARGET_ARCH)
+
+# Define default values for TOOLCHAIN_NAME, this can be overriden in
+# the setup file.
+TOOLCHAIN_NAME := $(TARGET_TOOLCHAIN)
+
+# Define the root path of the toolchain in the GDK tree.
+TOOLCHAIN_ROOT := $(GDK_ROOT)/toolchains/$(TOOLCHAIN_NAME)
+
+# Define the root path where toolchain prebuilts are stored
+TOOLCHAIN_PREBUILT_ROOT := $(TOOLCHAIN_ROOT)/prebuilt/bin
+
+# now call the toolchain-specific setup script
+include $(GDK_TOOLCHAIN.$(TARGET_TOOLCHAIN).setup)
+
+# compute GDK_APP_DST_DIR as the destination directory for the generated files
+GDK_APP_DST_DIR := $(GDK_APP_PROJECT_PATH)/res/raw
+
+clean-installed-binaries::
+
+# free the dictionary of LOCAL_MODULE definitions
+$(call modules-clear)
+
+# now parse the Android.mk for the application, this records all
+# module declarations, but does not populate the dependency graph yet.
+include $(GDK_APP_BUILD_SCRIPT)
+
+# now, really build the modules, the second pass allows one to deal
+# with exported values
+$(foreach __pass2_module,$(__gdk_modules),\
+ $(eval LOCAL_MODULE := $(__pass2_module))\
+ $(eval include $(BUILD_SYSTEM)/build-binary.mk)\
+)
+
+# Now compute the closure of all module dependencies.
+#
+# If APP_MODULES is not defined in the Application.mk, we
+# will build all modules that were listed from the top-level Android.mk
+#
+ifeq ($(strip $(GDK_APP_MODULES)),)
+ WANTED_MODULES := $(call modules-get-top-list)
+else
+ WANTED_MODULES := $(call module-get-all-dependencies,$(GDK_APP_MODULES))
+endif
+
+WANTED_INSTALLED_MODULES += $(call map,module-get-installed,$(WANTED_MODULES))
diff --git a/build/gmsl/README b/build/gmsl/README
new file mode 100644
index 0000000..152ada6
--- /dev/null
+++ b/build/gmsl/README
@@ -0,0 +1,27 @@
+GNU Make Standard Library
+-------------------------
+
+1. Visit http://gmsl.sf.net for more details
+
+2. To use the GMSL in your Makefile make sure that you have the files
+
+ gmsl
+ __gmsl
+
+ Add
+
+ include gmsl
+
+ to your Makefile(s).
+
+3. To run the GMSL test suite have
+
+ gmsl
+ __gmsl
+ gmsl-tests
+
+ And then run
+
+ make -f gmsl-tests
+
+ \ No newline at end of file
diff --git a/build/gmsl/__gmsl b/build/gmsl/__gmsl
new file mode 100644
index 0000000..596ff19
--- /dev/null
+++ b/build/gmsl/__gmsl
@@ -0,0 +1,854 @@
+# ----------------------------------------------------------------------------
+#
+# GNU Make Standard Library (GMSL)
+#
+# A library of functions to be used with GNU Make's $(call) that
+# provides functionality not available in standard GNU Make.
+#
+# Copyright (c) 2005-2007 John Graham-Cumming
+#
+# This file is part of GMSL
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of the John Graham-Cumming nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# ----------------------------------------------------------------------------
+
+# This is the GNU Make Standard Library version number as a list with
+# three items: major, minor, revision
+
+gmsl_version := 1 0 11
+
+# Used to output warnings and error from the library, it's possible to
+# disable any warnings or errors by overriding these definitions
+# manually or by setting GMSL_NO_WARNINGS or GMSL_NO_ERRORS
+
+__gmsl_name := GNU Make Standard Library
+__gmsl_warning = $(warning $(__gmsl_name): $1)
+__gmsl_error = $(error $(__gmsl_name): $1)
+
+ifdef GMSL_NO_WARNINGS
+__gmsl_warning :=
+endif
+ifdef GMSL_NO_ERRORS
+__gmsl_error :=
+endif
+
+# If GMSL_TRACE is enabled then calls to the library functions are
+# traced to stdout using warning messages with their arguments
+
+ifdef GMSL_TRACE
+__gmsl_tr1 = $(warning $0('$1'))
+__gmsl_tr2 = $(warning $0('$1','$2'))
+__gmsl_tr3 = $(warning $0('$1','$2','$3'))
+else
+__gmsl_tr1 :=
+__gmsl_tr2 :=
+__gmsl_tr3 :=
+endif
+
+# Figure out whether we have $(eval) or not (GNU Make 3.80 and above)
+# if we do not then output a warning message, if we do then some
+# functions will be enabled.
+
+__gmsl_have_eval := $(false)
+__gmsl_ignore := $(eval __gmsl_have_eval := $(true))
+
+# If this is being run with Electric Cloud's emake then warn that
+# their $(eval) support is incomplete.
+
+ifdef ECLOUD_BUILD_ID
+$(warning You are using Electric Cloud's emake which has incomplete $$(eval) support)
+__gmsl_have_eval := $(false)
+endif
+
+# See if we have $(lastword) (GNU Make 3.81 and above)
+
+__gmsl_have_lastword := $(lastword $(false) $(true))
+
+# See if we have native or and and (GNU Make 3.81 and above)
+
+__gmsl_have_or := $(if $(filter-out undefined, \
+ $(origin or)),$(call or,$(true),$(false)))
+__gmsl_have_and := $(if $(filter-out undefined, \
+ $(origin and)),$(call and,$(true),$(true)))
+
+ifneq ($(__gmsl_have_eval),$(true))
+$(call __gmsl_warning,GNU Make $(MAKE_VERSION) does not support $$$$(eval): some functions disabled)
+endif
+
+# ----------------------------------------------------------------------------
+# Function: gmsl_compatible
+# Arguments: List containing the desired library version number (maj min rev)
+# Returns: $(true) if this version of the library is compatible
+# with the requested version number, otherwise $(false)
+# ----------------------------------------------------------------------------
+gmsl_compatible = $(strip \
+ $(if $(call gt,$(word 1,$1),$(word 1,$(gmsl_version))), \
+ $(false), \
+ $(if $(call lt,$(word 1,$1),$(word 1,$(gmsl_version))), \
+ $(true), \
+ $(if $(call gt,$(word 2,$1),$(word 2,$(gmsl_version))), \
+ $(false), \
+ $(if $(call lt,$(word 2,$1),$(word 2,$(gmsl_version))), \
+ $(true), \
+ $(call lte,$(word 3,$1),$(word 3,$(gmsl_version))))))))
+
+# ###########################################################################
+# LOGICAL OPERATORS
+# ###########################################################################
+
+# not is defined in gmsl
+
+# ----------------------------------------------------------------------------
+# Function: and
+# Arguments: Two boolean values
+# Returns: Returns $(true) if both of the booleans are true
+# ----------------------------------------------------------------------------
+ifneq ($(__gmsl_have_and),$(true))
+and = $(__gmsl_tr2)$(if $1,$(if $2,$(true),$(false)),$(false))
+endif
+
+# ----------------------------------------------------------------------------
+# Function: or
+# Arguments: Two boolean values
+# Returns: Returns $(true) if either of the booleans is true
+# ----------------------------------------------------------------------------
+ifneq ($(__gmsl_have_or),$(true))
+or = $(__gmsl_tr2)$(if $1$2,$(true),$(false))
+endif
+
+# ----------------------------------------------------------------------------
+# Function: xor
+# Arguments: Two boolean values
+# Returns: Returns $(true) if exactly one of the booleans is true
+# ----------------------------------------------------------------------------
+xor = $(__gmsl_tr2)$(if $1,$(if $2,$(false),$(true)),$(if $2,$(true),$(false)))
+
+# ----------------------------------------------------------------------------
+# Function: nand
+# Arguments: Two boolean values
+# Returns: Returns value of 'not and'
+# ----------------------------------------------------------------------------
+nand = $(__gmsl_tr2)$(if $1,$(if $2,$(false),$(true)),$(true))
+
+# ----------------------------------------------------------------------------
+# Function: nor
+# Arguments: Two boolean values
+# Returns: Returns value of 'not or'
+# ----------------------------------------------------------------------------
+nor = $(__gmsl_tr2)$(if $1$2,$(false),$(true))
+
+# ----------------------------------------------------------------------------
+# Function: xnor
+# Arguments: Two boolean values
+# Returns: Returns value of 'not xor'
+# ----------------------------------------------------------------------------
+xnor =$(__gmsl_tr2)$(if $1,$(if $2,$(true),$(false)),$(if $2,$(false),$(true)))
+
+# ###########################################################################
+# LIST MANIPULATION FUNCTIONS
+# ###########################################################################
+
+# ----------------------------------------------------------------------------
+# Function: first (same as LISP's car, or head)
+# Arguments: 1: A list
+# Returns: Returns the first element of a list
+# ----------------------------------------------------------------------------
+first = $(__gmsl_tr1)$(firstword $1)
+
+# ----------------------------------------------------------------------------
+# Function: last
+# Arguments: 1: A list
+# Returns: Returns the last element of a list
+# ----------------------------------------------------------------------------
+ifeq ($(__gmsl_have_lastword),$(true))
+last = $(__gmsl_tr1)$(lastword $1)
+else
+last = $(__gmsl_tr1)$(if $1,$(word $(words $1),$1))
+endif
+
+# ----------------------------------------------------------------------------
+# Function: rest (same as LISP's cdr, or tail)
+# Arguments: 1: A list
+# Returns: Returns the list with the first element removed
+# ----------------------------------------------------------------------------
+rest = $(__gmsl_tr1)$(wordlist 2,$(words $1),$1)
+
+# ----------------------------------------------------------------------------
+# Function: chop
+# Arguments: 1: A list
+# Returns: Returns the list with the last element removed
+# ----------------------------------------------------------------------------
+chop = $(__gmsl_tr1)$(wordlist 2,$(words $1),x $1)
+
+# ----------------------------------------------------------------------------
+# Function: map
+# Arguments: 1: Name of function to $(call) for each element of list
+# 2: List to iterate over calling the function in 1
+# Returns: The list after calling the function on each element
+# ----------------------------------------------------------------------------
+map = $(__gmsl_tr2)$(strip $(foreach a,$2,$(call $1,$a)))
+
+# ----------------------------------------------------------------------------
+# Function: pairmap
+# Arguments: 1: Name of function to $(call) for each pair of elements
+# 2: List to iterate over calling the function in 1
+# 3: Second list to iterate over calling the function in 1
+# Returns: The list after calling the function on each pair of elements
+# ----------------------------------------------------------------------------
+pairmap = $(strip $(__gmsl_tr3)\
+ $(if $2$3,$(call $1,$(call first,$2),$(call first,$3)) \
+ $(call pairmap,$1,$(call rest,$2),$(call rest,$3))))
+
+# ----------------------------------------------------------------------------
+# Function: leq
+# Arguments: 1: A list to compare against...
+# 2: ...this list
+# Returns: Returns $(true) if the two lists are identical
+# ----------------------------------------------------------------------------
+leq = $(__gmsl_tr2)$(strip $(if $(call seq,$(words $1),$(words $2)), \
+ $(call __gmsl_list_equal,$1,$2),$(false)))
+
+__gmsl_list_equal = $(if $(strip $1), \
+ $(if $(call seq,$(call first,$1),$(call first,$2)), \
+ $(call __gmsl_list_equal, \
+ $(call rest,$1), \
+ $(call rest,$2)), \
+ $(false)), \
+ $(true))
+
+# ----------------------------------------------------------------------------
+# Function: lne
+# Arguments: 1: A list to compare against...
+# 2: ...this list
+# Returns: Returns $(true) if the two lists are different
+# ----------------------------------------------------------------------------
+lne = $(__gmsl_tr2)$(call not,$(call leq,$1,$2))
+
+# ----------------------------------------------------------------------------
+# Function: reverse
+# Arguments: 1: A list to reverse
+# Returns: The list with its elements in reverse order
+# ----------------------------------------------------------------------------
+reverse =$(__gmsl_tr1)$(strip $(if $1,$(call reverse,$(call rest,$1)) \
+ $(call first,$1)))
+
+# ----------------------------------------------------------------------------
+# Function: uniq
+# Arguments: 1: A list from which to remove repeated elements
+# Returns: The list with duplicate elements removed without reordering
+# ----------------------------------------------------------------------------
+uniq = $(strip $(__gmsl_tr1)$(if $1,$(call uniq,$(call chop,$1)) \
+ $(if $(filter $(call last,$1),$(call chop,$1)),,$(call last,$1))))
+
+# ----------------------------------------------------------------------------
+# Function: length
+# Arguments: 1: A list
+# Returns: The number of elements in the list
+# ----------------------------------------------------------------------------
+length = $(__gmsl_tr1)$(words $1)
+
+# ###########################################################################
+# STRING MANIPULATION FUNCTIONS
+# ###########################################################################
+
+# Helper function that translates any GNU Make 'true' value (i.e. a
+# non-empty string) to our $(true)
+
+__gmsl_make_bool = $(if $(strip $1),$(true),$(false))
+
+# ----------------------------------------------------------------------------
+# Function: seq
+# Arguments: 1: A string to compare against...
+# 2: ...this string
+# Returns: Returns $(true) if the two strings are identical
+# ----------------------------------------------------------------------------
+seq = $(__gmsl_tr2)$(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),$(false),$(true))
+
+# ----------------------------------------------------------------------------
+# Function: sne
+# Arguments: 1: A string to compare against...
+# 2: ...this string
+# Returns: Returns $(true) if the two strings are not the same
+# ----------------------------------------------------------------------------
+sne = $(__gmsl_tr2)$(call not,$(call seq,$1,$2))
+
+# ----------------------------------------------------------------------------
+# Function: split
+# Arguments: 1: The character to split on
+# 2: A string to split
+# Returns: Splits a string into a list separated by spaces at the split
+# character in the first argument
+# ----------------------------------------------------------------------------
+split = $(__gmsl_tr2)$(strip $(subst $1, ,$2))
+
+# ----------------------------------------------------------------------------
+# Function: merge
+# Arguments: 1: The character to put between fields
+# 2: A list to merge into a string
+# Returns: Merges a list into a single string, list elements are separated
+# by the character in the first argument
+# ----------------------------------------------------------------------------
+merge = $(__gmsl_tr2)$(strip $(if $2, \
+ $(if $(call seq,1,$(words $2)), \
+ $2,$(call first,$2)$1$(call merge,$1,$(call rest,$2)))))
+
+ifdef __gmsl_have_eval
+# ----------------------------------------------------------------------------
+# Function: tr
+# Arguments: 1: The list of characters to translate from
+# 2: The list of characters to translate to
+# 3: The text to translate
+# Returns: Returns the text after translating characters
+# ----------------------------------------------------------------------------
+tr = $(strip $(__gmsl_tr3)$(call assert_no_dollar,$0,$1$2$3) \
+ $(eval __gmsl_t := $3) \
+ $(foreach c, \
+ $(join $(addsuffix :,$1),$2), \
+ $(eval __gmsl_t := \
+ $(subst $(word 1,$(subst :, ,$c)),$(word 2,$(subst :, ,$c)), \
+ $(__gmsl_t))))$(__gmsl_t))
+
+# Common character classes for use with the tr function. Each of
+# these is actually a variable declaration and must be wrapped with
+# $() or ${} to be used.
+
+[A-Z] := A B C D E F G H I J K L M N O P Q R S T U V W X Y Z #
+[a-z] := a b c d e f g h i j k l m n o p q r s t u v w x y z #
+[0-9] := 0 1 2 3 4 5 6 7 8 9 #
+[A-F] := A B C D E F #
+
+# ----------------------------------------------------------------------------
+# Function: uc
+# Arguments: 1: Text to upper case
+# Returns: Returns the text in upper case
+# ----------------------------------------------------------------------------
+uc = $(__gmsl_tr1)$(call assert_no_dollar,$0,$1)$(call tr,$([a-z]),$([A-Z]),$1)
+
+# ----------------------------------------------------------------------------
+# Function: lc
+# Arguments: 1: Text to lower case
+# Returns: Returns the text in lower case
+# ----------------------------------------------------------------------------
+lc = $(__gmsl_tr1)$(call assert_no_dollar,$0,$1)$(call tr,$([A-Z]),$([a-z]),$1)
+
+# ----------------------------------------------------------------------------
+# Function: strlen
+# Arguments: 1: A string
+# Returns: Returns the length of the string
+# ----------------------------------------------------------------------------
+__gmsl_characters := A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
+__gmsl_characters += a b c d e f g h i j k l m n o p q r s t u v w x y z
+__gmsl_characters += 0 1 2 3 4 5 6 7 8 9
+__gmsl_characters += ` ~ ! @ \# $$ % ^ & * ( ) - _ = +
+__gmsl_characters += { } [ ] \ : ; ' " < > , . / ? |
+
+# Aside: if you read the above you might think that the lower-case
+# letter x is missing, and that that's an error. It is missing, but
+# it's not an error. __gmsl_characters is used by the strlen
+# function. strlen works by transforming every character and space
+# into the letter x and then counting the x's. Since there's no need
+# to transform x into x I omitted it.
+
+# This results in __gmsl_space containing just a space
+
+__gmsl_space :=
+__gmsl_space +=
+
+strlen = $(__gmsl_tr1)$(call assert_no_dollar,$0,$1)$(strip $(eval __temp := $(subst $(__gmsl_space),x,$1))$(foreach a,$(__gmsl_characters),$(eval __temp := $$(subst $$a,x,$(__temp))))$(eval __temp := $(subst x,x ,$(__temp)))$(words $(__temp)))
+
+# This results in __gmsl_newline containing just a newline
+
+define __gmsl_newline
+
+
+endef
+
+# This results in __gmsl_tab containing a tab
+
+__gmsl_tab := #
+
+# ----------------------------------------------------------------------------
+# Function: substr
+# Arguments: 1: A string
+# 2: Start position (first character is 1)
+# 3: End position (inclusive)
+# Returns: A substring.
+# Note: The string in $1 must not contain a §
+# ----------------------------------------------------------------------------
+
+substr = $(__gmsl_tr3)$(call assert_no_dollar,$0,$1$2$3)$(strip $(eval __temp := $$(subst $$(__gmsl_space),§ ,$$1))$(foreach a,$(__gmsl_characters),$(eval __temp := $$(subst $$a,$$a$$(__gmsl_space),$(__temp))))$(eval __temp := $(wordlist $2,$3,$(__temp))))$(subst §,$(__gmsl_space),$(subst $(__gmsl_space),,$(__temp)))
+
+endif # __gmsl_have_eval
+
+# ###########################################################################
+# SET MANIPULATION FUNCTIONS
+# ###########################################################################
+
+# Sets are represented by sorted, deduplicated lists. To create a set
+# from a list use set_create, or start with the empty_set and
+# set_insert individual elements
+
+# This is the empty set
+empty_set :=
+
+# ----------------------------------------------------------------------------
+# Function: set_create
+# Arguments: 1: A list of set elements
+# Returns: Returns the newly created set
+# ----------------------------------------------------------------------------
+set_create = $(__gmsl_tr1)$(sort $1)
+
+# ----------------------------------------------------------------------------
+# Function: set_insert
+# Arguments: 1: A single element to add to a set
+# 2: A set
+# Returns: Returns the set with the element added
+# ----------------------------------------------------------------------------
+set_insert = $(__gmsl_tr2)$(sort $1 $2)
+
+# ----------------------------------------------------------------------------
+# Function: set_remove
+# Arguments: 1: A single element to remove from a set
+# 2: A set
+# Returns: Returns the set with the element removed
+# ----------------------------------------------------------------------------
+set_remove = $(__gmsl_tr2)$(filter-out $1,$2)
+
+# ----------------------------------------------------------------------------
+# Function: set_is_member
+# Arguments: 1: A single element
+# 2: A set
+# Returns: Returns $(true) if the element is in the set
+# ----------------------------------------------------------------------------
+set_is_member = $(__gmsl_tr2)$(if $(filter $1,$2),$(true),$(false))
+
+# ----------------------------------------------------------------------------
+# Function: set_union
+# Arguments: 1: A set
+# 2: Another set
+# Returns: Returns the union of the two sets
+# ----------------------------------------------------------------------------
+set_union = $(__gmsl_tr2)$(sort $1 $2)
+
+# ----------------------------------------------------------------------------
+# Function: set_intersection
+# Arguments: 1: A set
+# 2: Another set
+# Returns: Returns the intersection of the two sets
+# ----------------------------------------------------------------------------
+set_intersection = $(__gmsl_tr2)$(filter $1,$2)
+
+# ----------------------------------------------------------------------------
+# Function: set_is_subset
+# Arguments: 1: A set
+# 2: Another set
+# Returns: Returns $(true) if the first set is a subset of the second
+# ----------------------------------------------------------------------------
+set_is_subset = $(__gmsl_tr2)$(call set_equal,$(call set_intersection,$1,$2),$1)
+
+# ----------------------------------------------------------------------------
+# Function: set_equal
+# Arguments: 1: A set
+# 2: Another set
+# Returns: Returns $(true) if the two sets are identical
+# ----------------------------------------------------------------------------
+set_equal = $(__gmsl_tr2)$(call seq,$1,$2)
+
+# ###########################################################################
+# ARITHMETIC LIBRARY
+# ###########################################################################
+
+# Integers a represented by lists with the equivalent number of x's.
+# For example the number 4 is x x x x. The maximum integer that the
+# library can handle as _input_ is __gmsl_input_int which is defined
+# here as 65536
+
+__gmsl_sixteen := x x x x x x x x x x x x x x x x
+__gmsl_input_int := $(foreach a,$(__gmsl_sixteen), \
+ $(foreach b,$(__gmsl_sixteen), \
+ $(foreach c,$(__gmsl_sixteen), \
+ $(__gmsl_sixteen)))))
+
+# ----------------------------------------------------------------------------
+# Function: int_decode
+# Arguments: 1: A number of x's representation
+# Returns: Returns the integer for human consumption that is represented
+# by the string of x's
+# ----------------------------------------------------------------------------
+int_decode = $(__gmsl_tr1)$(words $1)
+
+# ----------------------------------------------------------------------------
+# Function: int_encode
+# Arguments: 1: A number in human-readable integer form
+# Returns: Returns the integer encoded as a string of x's
+# ----------------------------------------------------------------------------
+int_encode = $(__gmsl_tr1)$(wordlist 1,$1,$(__gmsl_input_int))
+
+# The arithmetic library functions come in two forms: one form of each
+# function takes integers as arguments and the other form takes the
+# encoded form (x's created by a call to int_encode). For example,
+# there are two plus functions:
+#
+# plus Called with integer arguments and returns an integer
+# int_plus Called with encoded arguments and returns an encoded result
+#
+# plus will be slower than int_plus because its arguments and result
+# have to be translated between the x's format and integers. If doing
+# a complex calculation use the int_* forms with a single encoding of
+# inputs and single decoding of the output. For simple calculations
+# the direct forms can be used.
+
+# Helper function used to wrap an int_* function into a function that
+# takes a pair of integers, perhaps a function and returns an integer
+# result
+__gmsl_int_wrap = $(call int_decode,$(call $1,$(call int_encode,$2),$(call int_encode,$3)))
+__gmsl_int_wrap1 = $(call int_decode,$(call $1,$(call int_encode,$2)))
+__gmsl_int_wrap2 = $(call $1,$(call int_encode,$2),$(call int_encode,$3))
+
+# ----------------------------------------------------------------------------
+# Function: int_plus
+# Arguments: 1: A number in x's representation
+# 2: Another number in x's represntation
+# Returns: Returns the sum of the two numbers in x's representation
+# ----------------------------------------------------------------------------
+int_plus = $(strip $(__gmsl_tr2)$1 $2)
+
+# ----------------------------------------------------------------------------
+# Function: plus (wrapped version of int_plus)
+# Arguments: 1: An integer
+# 2: Another integer
+# Returns: Returns the sum of the two integers
+# ----------------------------------------------------------------------------
+plus = $(__gmsl_tr2)$(call __gmsl_int_wrap,int_plus,$1,$2)
+
+# ----------------------------------------------------------------------------
+# Function: int_subtract
+# Arguments: 1: A number in x's representation
+# 2: Another number in x's represntation
+# Returns: Returns the difference of the two numbers in x's representation,
+# or outputs an error on a numeric underflow
+# ----------------------------------------------------------------------------
+int_subtract = $(strip $(__gmsl_tr2)$(if $(call int_gte,$1,$2), \
+ $(filter-out xx,$(join $1,$2)), \
+ $(call __gmsl_warning,Subtraction underflow)))
+
+# ----------------------------------------------------------------------------
+# Function: subtract (wrapped version of int_subtract)
+# Arguments: 1: An integer
+# 2: Another integer
+# Returns: Returns the difference of the two integers,
+# or outputs an error on a numeric underflow
+# ----------------------------------------------------------------------------
+subtract = $(__gmsl_tr2)$(call __gmsl_int_wrap,int_subtract,$1,$2)
+
+# ----------------------------------------------------------------------------
+# Function: int_multiply
+# Arguments: 1: A number in x's representation
+# 2: Another number in x's represntation
+# Returns: Returns the product of the two numbers in x's representation
+# ----------------------------------------------------------------------------
+int_multiply = $(strip $(__gmsl_tr2)$(foreach a,$1,$2))
+
+# ----------------------------------------------------------------------------
+# Function: multiply (wrapped version of int_multiply)
+# Arguments: 1: An integer
+# 2: Another integer
+# Returns: Returns the product of the two integers
+# ----------------------------------------------------------------------------
+multiply = $(__gmsl_tr2)$(call __gmsl_int_wrap,int_multiply,$1,$2)
+
+# ----------------------------------------------------------------------------
+# Function: int_divide
+# Arguments: 1: A number in x's representation
+# 2: Another number in x's represntation
+# Returns: Returns the result of integer division of argument 1 divided
+# by argument 2 in x's representation
+# ----------------------------------------------------------------------------
+int_divide = $(__gmsl_tr2)$(strip $(if $2, \
+ $(if $(call int_gte,$1,$2), \
+ x $(call int_divide,$(call int_subtract,$1,$2),$2),), \
+ $(call __gmsl_error,Division by zero)))
+
+# ----------------------------------------------------------------------------
+# Function: divide (wrapped version of int_divide)
+# Arguments: 1: An integer
+# 2: Another integer
+# Returns: Returns the integer division of the first argument by the second
+# ----------------------------------------------------------------------------
+divide = $(__gmsl_tr2)$(call __gmsl_int_wrap,int_divide,$1,$2)
+
+# ----------------------------------------------------------------------------
+# Function: int_max, int_min
+# Arguments: 1: A number in x's representation
+# 2: Another number in x's represntation
+# Returns: Returns the maximum or minimum of its arguments in x's
+# representation
+# ----------------------------------------------------------------------------
+int_max = $(__gmsl_tr2)$(subst xx,x,$(join $1,$2))
+int_min = $(__gmsl_tr2)$(subst xx,x,$(filter xx,$(join $1,$2)))
+
+# ----------------------------------------------------------------------------
+# Function: max, min
+# Arguments: 1: An integer
+# 2: Another integer
+# Returns: Returns the maximum or minimum of its integer arguments
+# ----------------------------------------------------------------------------
+max = $(__gmsl_tr2)$(call __gmsl_int_wrap,int_max,$1,$2)
+min = $(__gmsl_tr2)$(call __gmsl_int_wrap,int_min,$1,$2)
+
+# ----------------------------------------------------------------------------
+# Function: int_gt, int_gte, int_lt, int_lte, int_eq, int_ne
+# Arguments: Two x's representation numbers to be compared
+# Returns: $(true) or $(false)
+#
+# int_gt First argument greater than second argument
+# int_gte First argument greater than or equal to second argument
+# int_lt First argument less than second argument
+# int_lte First argument less than or equal to second argument
+# int_eq First argument is numerically equal to the second argument
+# int_ne First argument is not numerically equal to the second argument
+# ----------------------------------------------------------------------------
+int_gt = $(__gmsl_tr2)$(call __gmsl_make_bool, \
+ $(filter-out $(words $2), \
+ $(words $(call int_max,$1,$2))))
+int_gte = $(__gmsl_tr2)$(call __gmsl_make_bool, \
+ $(call int_gt,$1,$2)$(call int_eq,$1,$2))
+int_lt = $(__gmsl_tr2)$(call __gmsl_make_bool, \
+ $(filter-out $(words $1), \
+ $(words $(call int_max,$1,$2))))
+int_lte = $(__gmsl_tr2)$(call __gmsl_make_bool, \
+ $(call int_lt,$1,$2)$(call int_eq,$1,$2))
+int_eq = $(__gmsl_tr2)$(call __gmsl_make_bool, \
+ $(filter $(words $1),$(words $2)))
+int_ne = $(__gmsl_tr2)$(call __gmsl_make_bool, \
+ $(filter-out $(words $1),$(words $2)))
+
+# ----------------------------------------------------------------------------
+# Function: gt, gte, lt, lte, eq, ne
+# Arguments: Two integers to be compared
+# Returns: $(true) or $(false)
+#
+# gt First argument greater than second argument
+# gte First argument greater than or equal to second argument
+# lt First argument less than second argument
+# lte First argument less than or equal to second argument
+# eq First argument is numerically equal to the second argument
+# ne First argument is not numerically equal to the second argument
+# ----------------------------------------------------------------------------
+gt = $(__gmsl_tr2)$(call __gmsl_int_wrap2,int_gt,$1,$2)
+gte = $(__gmsl_tr2)$(call __gmsl_int_wrap2,int_gte,$1,$2)
+lt = $(__gmsl_tr2)$(call __gmsl_int_wrap2,int_lt,$1,$2)
+lte = $(__gmsl_tr2)$(call __gmsl_int_wrap2,int_lte,$1,$2)
+eq = $(__gmsl_tr2)$(call __gmsl_int_wrap2,int_eq,$1,$2)
+ne = $(__gmsl_tr2)$(call __gmsl_int_wrap2,int_ne,$1,$2)
+
+# increment adds 1 to its argument, decrement subtracts 1. Note that
+# decrement does not range check and hence will not underflow, but
+# will incorrectly say that 0 - 1 = 0
+
+# ----------------------------------------------------------------------------
+# Function: int_inc
+# Arguments: 1: A number in x's representation
+# Returns: The number incremented by 1 in x's representation
+# ----------------------------------------------------------------------------
+int_inc = $(strip $(__gmsl_tr1)$1 x)
+
+# ----------------------------------------------------------------------------
+# Function: inc
+# Arguments: 1: An integer
+# Returns: The argument incremented by 1
+# ----------------------------------------------------------------------------
+inc = $(__gmsl_tr1)$(call __gmsl_int_wrap1,int_inc,$1)
+
+# ----------------------------------------------------------------------------
+# Function: int_dec
+# Arguments: 1: A number in x's representation
+# Returns: The number decremented by 1 in x's representation
+# ----------------------------------------------------------------------------
+int_dec = $(__gmsl_tr1)$(strip $(if $(call sne,0,$(words $1)), \
+ $(wordlist 2,$(words $1),$1), \
+ $(call __gmsl_warning,Decrement underflow)))
+
+# ----------------------------------------------------------------------------
+# Function: dec
+# Arguments: 1: An integer
+# Returns: The argument decremented by 1
+# ----------------------------------------------------------------------------
+dec = $(__gmsl_tr1)$(call __gmsl_int_wrap1,int_dec,$1)
+
+# double doubles its argument, and halve halves it
+
+# ----------------------------------------------------------------------------
+# Function: int_double
+# Arguments: 1: A number in x's representation
+# Returns: The number doubled (i.e. * 2) and returned in x's representation
+# ----------------------------------------------------------------------------
+int_double = $(strip $(__gmsl_tr1)$1 $1)
+
+# ----------------------------------------------------------------------------
+# Function: double
+# Arguments: 1: An integer
+# Returns: The integer times 2
+# ----------------------------------------------------------------------------
+double = $(__gmsl_tr1)$(call __gmsl_int_wrap1,int_double,$1)
+
+# ----------------------------------------------------------------------------
+# Function: int_halve
+# Arguments: 1: A number in x's representation
+# Returns: The number halved (i.e. / 2) and returned in x's representation
+# ----------------------------------------------------------------------------
+int_halve = $(__gmsl_tr1)$(strip $(subst xx,x,$(filter-out xy x y, \
+ $(join $1,$(foreach a,$1,y x)))))
+
+# ----------------------------------------------------------------------------
+# Function: halve
+# Arguments: 1: An integer
+# Returns: The integer divided by 2
+# ----------------------------------------------------------------------------
+halve = $(__gmsl_tr1)$(call __gmsl_int_wrap1,int_halve,$1)
+
+ifdef __gmsl_have_eval
+# ###########################################################################
+# ASSOCIATIVE ARRAYS
+# ###########################################################################
+
+# ----------------------------------------------------------------------------
+# Function: set
+# Arguments: 1: Name of associative array
+# 2: The key value to associate
+# 3: The value associated with the key
+# Returns: None
+# ----------------------------------------------------------------------------
+set = $(__gmsl_tr3)$(call assert_no_dollar,$0,$1$2$3)$(eval __gmsl_aa_$1_$2 = $3)
+
+# ----------------------------------------------------------------------------
+# Function: get
+# Arguments: 1: Name of associative array
+# 2: The key to retrieve
+# Returns: The value stored in the array for that key
+# ----------------------------------------------------------------------------
+get = $(strip $(__gmsl_tr2)$(call assert_no_dollar,$0,$1$2)$(if $(filter-out undefined,$(origin __gmsl_aa_$1_$2)), \
+ $(__gmsl_aa_$1_$2)))
+
+# ----------------------------------------------------------------------------
+# Function: keys
+# Arguments: 1: Name of associative array
+# Returns: Returns a list of all defined keys in the array
+# ----------------------------------------------------------------------------
+keys = $(__gmsl_tr1)$(call assert_no_dollar,$0,$1)$(sort $(patsubst __gmsl_aa_$1_%,%, \
+ $(filter __gmsl_aa_$1_%,$(.VARIABLES))))
+
+# ----------------------------------------------------------------------------
+# Function: defined
+# Arguments: 1: Name of associative array
+# 2: The key to test
+# Returns: Returns true if the key is defined (i.e. not empty)
+# ----------------------------------------------------------------------------
+defined = $(__gmsl_tr2)$(call assert_no_dollar,$0,$1$2)$(call sne,$(call get,$1,$2),)
+
+endif # __gmsl_have_eval
+
+ifdef __gmsl_have_eval
+# ###########################################################################
+# NAMED STACKS
+# ###########################################################################
+
+# ----------------------------------------------------------------------------
+# Function: push
+# Arguments: 1: Name of stack
+# 2: Value to push onto the top of the stack (must not contain
+# a space)
+# Returns: None
+# ----------------------------------------------------------------------------
+push = $(__gmsl_tr2)$(call assert_no_dollar,$0,$1$2)$(eval __gmsl_stack_$1 := $2 $(if $(filter-out undefined,\
+ $(origin __gmsl_stack_$1)),$(__gmsl_stack_$1)))
+
+# ----------------------------------------------------------------------------
+# Function: pop
+# Arguments: 1: Name of stack
+# Returns: Top element from the stack after removing it
+# ----------------------------------------------------------------------------
+pop = $(__gmsl_tr1)$(call assert_no_dollar,$0,$1)$(strip $(if $(filter-out undefined,$(origin __gmsl_stack_$1)), \
+ $(call first,$(__gmsl_stack_$1)) \
+ $(eval __gmsl_stack_$1 := $(call rest,$(__gmsl_stack_$1)))))
+
+# ----------------------------------------------------------------------------
+# Function: peek
+# Arguments: 1: Name of stack
+# Returns: Top element from the stack without removing it
+# ----------------------------------------------------------------------------
+peek = $(__gmsl_tr1)$(call assert_no_dollar,$0,$1)$(call first,$(__gmsl_stack_$1))
+
+# ----------------------------------------------------------------------------
+# Function: depth
+# Arguments: 1: Name of stack
+# Returns: Number of items on the stack
+# ----------------------------------------------------------------------------
+depth = $(__gmsl_tr1)$(call assert_no_dollar,$0,$1)$(words $(__gmsl_stack_$1))
+
+endif # __gmsl_have_eval
+
+# ###########################################################################
+# DEBUGGING FACILITIES
+# ###########################################################################
+
+# ----------------------------------------------------------------------------
+# Target: gmsl-print-%
+# Arguments: The % should be replaced by the name of a variable that you
+# wish to print out.
+# Action: Echos the name of the variable that matches the % and its value.
+# For example, 'make gmsl-print-SHELL' will output the value of
+# the SHELL variable
+# ----------------------------------------------------------------------------
+gmsl-print-%: ; @echo $* = $($*)
+
+# ----------------------------------------------------------------------------
+# Function: assert
+# Arguments: 1: A boolean that must be true or the assertion will fail
+# 2: The message to print with the assertion
+# Returns: None
+# ----------------------------------------------------------------------------
+assert = $(if $1,,$(call __gmsl_error,Assertion failure: $2))
+
+# ----------------------------------------------------------------------------
+# Function: assert_exists
+# Arguments: 1: Name of file that must exist, if it is missing an assertion
+# will be generated
+# Returns: None
+# ----------------------------------------------------------------------------
+assert_exists = $(call assert,$(wildcard $1),file '$1' missing)
+
+# ----------------------------------------------------------------------------
+# Function: assert_no_dollar
+# Arguments: 1: Name of a function being executd
+# 2: Arguments to check
+# Returns: None
+# ----------------------------------------------------------------------------
+assert_no_dollar = $(call assert,$(call not,$(findstring $$,$2)),$1 called with a dollar sign in argument)
diff --git a/build/gmsl/gmsl b/build/gmsl/gmsl
new file mode 100644
index 0000000..2ff2897
--- /dev/null
+++ b/build/gmsl/gmsl
@@ -0,0 +1,89 @@
+# ----------------------------------------------------------------------------
+#
+# GNU Make Standard Library (GMSL)
+#
+# A library of functions to be used with GNU Make's $(call) that
+# provides functionality not available in standard GNU Make.
+#
+# Copyright (c) 2005-2008 John Graham-Cumming
+#
+# This file is part of GMSL
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of the John Graham-Cumming nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# ----------------------------------------------------------------------------
+
+# Determine if the library has already been included and if so don't
+# bother including it again
+
+ifndef __gmsl_included
+
+# Standard definitions for true and false. true is any non-empty
+# string, false is an empty string. These are intended for use with
+# $(if).
+
+true := T
+false :=
+
+# ----------------------------------------------------------------------------
+# Function: not
+# Arguments: 1: A boolean value
+# Returns: Returns the opposite of the arg. (true -> false, false -> true)
+# ----------------------------------------------------------------------------
+not = $(if $1,$(false),$(true))
+
+# Prevent reinclusion of the library
+
+__gmsl_included := $(true)
+
+# Try to determine where this file is located. If the caller did
+# include /foo/gmsl then extract the /foo/ so that __gmsl gets
+# included transparently
+
+ifneq ($(MAKEFILE_LIST),)
+__gmsl_root := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
+
+# If there are any spaces in the path in __gmsl_root then give up
+
+ifeq (1,$(words $(__gmsl_root)))
+__gmsl_root := $(patsubst %gmsl,%,$(__gmsl_root))
+else
+__gmsl_root :=
+endif
+
+include $(__gmsl_root)__gmsl
+
+else
+
+include __gmsl
+
+endif
+
+endif # __gmsl_included
+
diff --git a/build/gmsl/gmsl-tests b/build/gmsl/gmsl-tests
new file mode 100644
index 0000000..b205be6
--- /dev/null
+++ b/build/gmsl/gmsl-tests
@@ -0,0 +1,647 @@
+# ----------------------------------------------------------------------------
+#
+# GNU Make Standard Library (GMSL) Test Suite
+#
+# Test suite for the GMSL
+#
+# Copyright (c) 2005-2007 John Graham-Cumming
+#
+# This file is part of GMSL
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of the John Graham-Cumming nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# ----------------------------------------------------------------------------
+
+.PHONY: all
+all:
+ @echo
+ @echo Test Summary
+ @echo ------------
+ @echo "$(call int_decode,$(passed)) tests passed; $(call int_decode,$(failed)) tests failed"
+
+include gmsl
+
+passed :=
+failed :=
+
+ECHO := /bin/echo
+
+start_test = $(shell $(ECHO) -n "Testing '$1': " >&2)$(eval current_test := OK)
+stop_test = $(shell $(ECHO) " $(current_test)" >&2)
+test_pass = .$(eval passed := $(call int_inc,$(passed)))
+test_fail = X$(eval failed := $(call int_inc,$(failed)))$(eval current_test := ERROR '$1' != '$2')
+test_assert = $(if $(filter undefined,$(origin 2)),$(eval 2 :=))$(shell $(ECHO) -n $(if $(call seq,$1,$2),$(call test_pass,$1,$2),$(call test_fail,$1,$2)) >&2)
+
+$(call start_test,not)
+$(call test_assert,$(call not,$(true)),$(false))
+$(call test_assert,$(call not,$(false)),$(true))
+$(call stop_test)
+
+$(call start_test,or)
+$(call test_assert,$(call or,$(true),$(true)),$(true))
+$(call test_assert,$(call or,$(true),$(false)),$(true))
+$(call test_assert,$(call or,$(false),$(true)),$(true))
+$(call test_assert,$(call or,$(false),$(false)),$(false))
+$(call stop_test)
+
+$(call start_test,and)
+$(call test_assert,$(call and,$(true),$(true)),$(true))
+$(call test_assert,$(call and,$(true),$(false)),$(false))
+$(call test_assert,$(call and,$(false),$(true)),$(false))
+$(call test_assert,$(call and,$(false),$(false)),$(false))
+$(call stop_test)
+
+$(call start_test,xor)
+$(call test_assert,$(call xor,$(true),$(true)),$(false))
+$(call test_assert,$(call xor,$(true),$(false)),$(true))
+$(call test_assert,$(call xor,$(false),$(true)),$(true))
+$(call test_assert,$(call xor,$(false),$(false)),$(false))
+$(call stop_test)
+
+$(call start_test,nand)
+$(call test_assert,$(call nand,$(true),$(true)),$(false))
+$(call test_assert,$(call nand,$(true),$(false)),$(true))
+$(call test_assert,$(call nand,$(false),$(true)),$(true))
+$(call test_assert,$(call nand,$(false),$(false)),$(true))
+$(call stop_test)
+
+$(call start_test,nor)
+$(call test_assert,$(call nor,$(true),$(true)),$(false))
+$(call test_assert,$(call nor,$(true),$(false)),$(false))
+$(call test_assert,$(call nor,$(false),$(true)),$(false))
+$(call test_assert,$(call nor,$(false),$(false)),$(true))
+$(call stop_test)
+
+$(call start_test,xnor)
+$(call test_assert,$(call xnor,$(true),$(true)),$(true))
+$(call test_assert,$(call xnor,$(true),$(false)),$(false))
+$(call test_assert,$(call xnor,$(false),$(true)),$(false))
+$(call test_assert,$(call xnor,$(false),$(false)),$(true))
+$(call stop_test)
+
+$(call start_test,first)
+$(call test_assert,$(call first,1 2 3),1)
+$(call test_assert,$(call first,1),1)
+$(call test_assert,$(call first,),)
+$(call stop_test)
+
+$(call start_test,last)
+$(call test_assert,$(call last,1 2 3),3)
+$(call test_assert,$(call last,1),1)
+$(call test_assert,$(call last,),)
+$(call stop_test)
+
+$(call start_test,rest)
+$(call test_assert,$(call rest,1 2 3),2 3)
+$(call test_assert,$(call rest,1),)
+$(call test_assert,$(call rest,),)
+$(call stop_test)
+
+$(call start_test,chop)
+$(call test_assert,$(call chop,1 2 3),1 2)
+$(call test_assert,$(call chop,1 2 3 4),1 2 3)
+$(call test_assert,$(call chop,1),)
+$(call test_assert,$(call chop,),)
+$(call stop_test)
+
+$(call start_test,length)
+$(call test_assert,$(call length,1 2 3),3)
+$(call test_assert,$(call length,1 2 3 4),4)
+$(call test_assert,$(call length,1),1)
+$(call test_assert,$(call length,),0)
+$(call stop_test)
+
+$(call start_test,map)
+$(call test_assert,$(call map,origin,__undefined map MAKE),undefined file default)
+$(call test_assert,$(call map,origin,),)
+$(call stop_test)
+
+joinem = $1$2
+$(call start_test,pairmap)
+$(call test_assert,$(call pairmap,addsuffix,2 1 3,a b c),a2 b1 c3)
+$(call test_assert,$(call pairmap,addprefix,2 1 3,a b c d),2a 1b 3c d)
+$(call test_assert,$(call pairmap,addprefix,2 1 3 4,a b c),2a 1b 3c)
+$(call test_assert,$(call pairmap,joinem,2 1 3 4,a b c),2a 1b 3c 4)
+$(call stop_test)
+
+$(call start_test,seq)
+$(call test_assert,$(call seq,abc,abc),T)
+$(call test_assert,$(call seq,x,),)
+$(call test_assert,$(call seq,,x),)
+$(call test_assert,$(call seq,x,x),T)
+$(call test_assert,$(call seq,a%c,abc),)
+$(call test_assert,$(call seq,abc,a%c),)
+$(call test_assert,$(call seq,abc,ABC),)
+$(call test_assert,$(call seq,abc,),)
+$(call test_assert,$(call seq,,),T)
+$(call test_assert,$(call seq,a b c,a b c),T)
+$(call test_assert,$(call seq,aa% bb% cc,aa% bb% cc),T)
+$(call test_assert,$(call seq,aa% bb% cc,aa% bb cc),)
+$(call test_assert,$(call seq,aa% bb% cc,xx yy zz),)
+$(call stop_test)
+
+$(call start_test,sne)
+$(call test_assert,$(call sne,abc,abc),)
+$(call test_assert,$(call sne,x,),T)
+$(call test_assert,$(call sne,,x),T)
+$(call test_assert,$(call sne,x,x),)
+$(call test_assert,$(call sne,abc,ABC),T)
+$(call test_assert,$(call sne,abc,),T)
+$(call test_assert,$(call sne,,),)
+$(call test_assert,$(call sne,a b c,a b c),)
+$(call test_assert,$(call sne,aa% bb% cc,aa% bb% cc),)
+$(call test_assert,$(call sne,aa% bb% cc,aa% bb cc),T)
+$(call stop_test)
+
+$(call start_test,strlen)
+$(call test_assert,$(call strlen,),0)
+$(call test_assert,$(call strlen,a),1)
+$(call test_assert,$(call strlen,a b),3)
+$(call test_assert,$(call strlen,a ),2)
+$(call test_assert,$(call strlen, a),2)
+$(call test_assert,$(call strlen, ),2)
+$(call test_assert,$(call strlen, ),3)
+$(call test_assert,$(call strlen, ),4)
+$(call stop_test)
+
+$(call start_test,substr)
+$(call test_assert,$(call substr,xyz,1,1),x)
+$(call test_assert,$(call substr,xyz,1,2),xy)
+$(call test_assert,$(call substr,xyz,2,3),yz)
+$(call test_assert,$(call substr,some string,1,1),s)
+$(call test_assert,$(call substr,some string,1,2),so)
+$(call test_assert,$(call substr,some string,1,3),som)
+$(call test_assert,$(call substr,some string,1,4),some)
+$(call test_assert,$(call substr,some string,1,5),some )
+$(call test_assert,$(call substr,some string,1,6),some s)
+$(call test_assert,$(call substr,some string,5,5), )
+$(call test_assert,$(call substr,some string,5,6), s)
+$(call test_assert,$(call substr,some string,5,7), st)
+$(call test_assert,$(call substr,some string,5,8), str)
+$(call test_assert,$(call substr,some string,1,100),some string)
+$(call stop_test)
+
+$(call start_test,lc)
+$(call test_assert,$(call lc,The Quick Brown Fox),the quick brown fox)
+$(call test_assert,$(call lc,the1 quick2 brown3 fox4),the1 quick2 brown3 fox4)
+$(call test_assert,$(call lc,The_),the_)
+$(call test_assert,$(call lc,),)
+$(call stop_test)
+
+$(call start_test,uc)
+$(call test_assert,$(call uc,The Quick Brown Fox),THE QUICK BROWN FOX)
+$(call test_assert,$(call uc,the1 quick2 brown3 fox4),THE1 QUICK2 BROWN3 FOX4)
+$(call test_assert,$(call uc,The_),THE_)
+$(call test_assert,$(call uc,),)
+$(call stop_test)
+
+$(call start_test,tr)
+$(call test_assert,$(call tr,A B C,1 2 3,CAPITAL),31PIT1L)
+$(call test_assert,$(call tr,a b c,1 2 3,CAPITAL),CAPITAL)
+$(call test_assert,$(call tr,E L I,3 1 1,I AM ELITE),1 AM 311T3)
+$(call stop_test)
+
+$(call start_test,leq)
+$(call test_assert,$(call leq,1 2 3,1 2 3),T)
+$(call test_assert,$(call leq,1 2 3,1 2 3 4),)
+$(call test_assert,$(call leq,1 2 3 4,1 2 3),)
+$(call test_assert,$(call leq,1,1),T)
+$(call test_assert,$(call leq,,),T)
+$(call stop_test)
+
+$(call start_test,lne)
+$(call test_assert,$(call lne,1 2 3,1 2 3),)
+$(call test_assert,$(call lne,1 2 3,1 2 3 4),T)
+$(call test_assert,$(call lne,1 2 3 4,1 2 3),T)
+$(call test_assert,$(call lne,1,1),)
+$(call test_assert,$(call lne,,),)
+$(call stop_test)
+
+$(call start_test,empty_set)
+$(call test_assert,$(empty_set),)
+$(call test_assert,$(empty_set),$(call set_create,))
+$(call stop_test)
+
+$(call start_test,set_create)
+$(call test_assert,$(call set_create,),)
+$(call test_assert,$(call set_create,1 2 2 3),1 2 3)
+$(call test_assert,$(call set_create,2 1 1 2 2 3),1 2 3)
+$(call test_assert,$(call set_create,1),1)
+$(call stop_test)
+
+$(call start_test,set_insert)
+$(call test_assert,$(call set_insert,1,$(empty_set)),1)
+$(call test_assert,$(call set_insert,1,$(call set_create,1)),1)
+$(call test_assert,$(call set_insert,1,$(call set_create,1 2)),1 2)
+$(call test_assert,$(call set_insert,0,$(call set_create,1 2)),0 1 2)
+$(call stop_test)
+
+$(call start_test,set_remove)
+$(call test_assert,$(call set_remove,1,$(empty_set)),$(empty_set))
+$(call test_assert,$(call set_remove,1,$(call set_create,1 2)),2)
+$(call test_assert,$(call set_remove,1,$(call set_create,1 11 2)),11 2)
+$(call test_assert,$(call set_remove,0,$(call set_create,1 2)),1 2)
+$(call stop_test)
+
+$(call start_test,set_is_member)
+$(call test_assert,$(call set_is_member,1,$(empty_set)),)
+$(call test_assert,$(call set_is_member,1,$(call set_create,2 3)),)
+$(call test_assert,$(call set_is_member,1,$(call set_create,1 2 3)),T)
+$(call test_assert,$(call set_is_member,1,$(call set_create,1)),T)
+$(call stop_test)
+
+$(call start_test,set_union)
+$(call test_assert,$(call set_union,,),)
+$(call test_assert,$(call set_union,1 2,),1 2)
+$(call test_assert,$(call set_union,,3 4),3 4)
+$(call test_assert,$(call set_union,1 2,3 4),1 2 3 4)
+$(call test_assert,$(call set_union,1 2 3,3 4 5),1 2 3 4 5)
+$(call stop_test)
+
+$(call start_test,set_intersection)
+$(call test_assert,$(call set_intersection,,),)
+$(call test_assert,$(call set_intersection,1 2,),)
+$(call test_assert,$(call set_intersection,,3 4),)
+$(call test_assert,$(call set_intersection,1 2,3 4),)
+$(call test_assert,$(call set_intersection,1 2 3 4,3 4 5),3 4)
+$(call stop_test)
+
+$(call start_test,set_is_subset)
+$(call test_assert,$(call set_is_subset,,),T)
+$(call test_assert,$(call set_is_subset,1 2,),)
+$(call test_assert,$(call set_is_subset,,3 4),T)
+$(call test_assert,$(call set_is_subset,1 2,3 4),)
+$(call test_assert,$(call set_is_subset,1 2,1 2 3 4 5),T)
+$(call test_assert,$(call set_is_subset,1 2,1 2),T)
+$(call test_assert,$(call set_is_subset,1 2,1 3 4 5),)
+$(call stop_test)
+
+$(call start_test,set_equal)
+$(call test_assert,$(call set_equal,,),T)
+$(call test_assert,$(call set_equal,1,),)
+$(call test_assert,$(call set_equal,,1),)
+$(call test_assert,$(call set_equal,1,1),T)
+$(call test_assert,$(call set_equal,1 2,),)
+$(call test_assert,$(call set_equal,,1 2),)
+$(call test_assert,$(call set_equal,1 2,1 2 3),)
+$(call stop_test)
+
+$(call start_test,int_encode)
+$(call test_assert,$(call int_encode,0),)
+$(call test_assert,$(call int_encode,1),x)
+$(call test_assert,$(call int_encode,2),x x)
+$(call test_assert,$(call int_encode,10),x x x x x x x x x x)
+$(call stop_test)
+
+$(call start_test,int_decode)
+$(call test_assert,$(call int_decode,),0)
+$(call test_assert,$(call int_decode,x),1)
+$(call test_assert,$(call int_decode,x x),2)
+$(call test_assert,$(call int_decode,x x x x x x x x x x),10)
+$(call stop_test)
+
+$(call start_test,int_plus)
+$(call test_assert,$(call int_plus,$(call int_encode,3),$(call int_encode,4)),$(call int_encode,7))
+$(call test_assert,$(call int_plus,$(call int_encode,0),$(call int_encode,4)),$(call int_encode,4))
+$(call test_assert,$(call int_plus,$(call int_encode,3),$(call int_encode,0)),$(call int_encode,3))
+$(call test_assert,$(call int_plus,$(call int_encode,0),$(call int_encode,0)),$(call int_encode,0))
+$(call test_assert,$(call int_plus,$(call int_encode,1),$(call int_encode,0)),$(call int_encode,1))
+$(call stop_test)
+
+$(call start_test,plus)
+$(call test_assert,$(call plus,3,4),7)
+$(call test_assert,$(call plus,4,3),7)
+$(call test_assert,$(call plus,0,4),4)
+$(call test_assert,$(call plus,3,0),3)
+$(call test_assert,$(call plus,0,0),0)
+$(call stop_test)
+
+__gmsl_warning = $1
+$(call start_test,int_subtract)
+$(call test_assert,$(call int_subtract,$(call int_encode,3),$(call int_encode,4)),Subtraction underflow)
+$(call test_assert,$(call int_subtract,$(call int_encode,4),$(call int_encode,3)),$(call int_encode,1))
+$(call test_assert,$(call int_subtract,$(call int_encode,3),$(call int_encode,0)),$(call int_encode,3))
+$(call test_assert,$(call int_subtract,$(call int_encode,0),$(call int_encode,0)),$(call int_encode,0))
+$(call test_assert,$(call int_subtract,$(call int_encode,1),$(call int_encode,0)),$(call int_encode,1))
+$(call stop_test)
+
+__gmsl_warning = x x x x x x x x x x
+$(call start_test,subtract)
+$(call test_assert,$(call subtract,3,4),10)
+$(call test_assert,$(call subtract,4,3),1)
+$(call test_assert,$(call subtract,3,0),3)
+$(call test_assert,$(call subtract,0,0),0)
+$(call stop_test)
+
+$(call start_test,int_multiply)
+$(call test_assert,$(call int_multiply,$(call int_encode,3),$(call int_encode,4)),$(call int_encode,12))
+$(call test_assert,$(call int_multiply,$(call int_encode,4),$(call int_encode,3)),$(call int_encode,12))
+$(call test_assert,$(call int_multiply,$(call int_encode,3),$(call int_encode,0)),$(call int_encode,0))
+$(call test_assert,$(call int_multiply,$(call int_encode,0),$(call int_encode,0)),$(call int_encode,0))
+$(call test_assert,$(call int_multiply,$(call int_encode,1),$(call int_encode,0)),$(call int_encode,0))
+$(call stop_test)
+
+$(call start_test,multiply)
+$(call test_assert,$(call multiply,3,4),12)
+$(call test_assert,$(call multiply,4,3),12)
+$(call test_assert,$(call multiply,3,0),0)
+$(call test_assert,$(call multiply,0,3),0)
+$(call test_assert,$(call multiply,0,0),0)
+$(call stop_test)
+
+__gmsl_error = $1
+$(call start_test,int_divide)
+$(call test_assert,$(call int_divide,$(call int_encode,3),$(call int_encode,4)),$(call int_encode,0))
+$(call test_assert,$(call int_divide,$(call int_encode,4),$(call int_encode,3)),$(call int_encode,1))
+$(call test_assert,$(call int_divide,$(call int_encode,31),$(call int_encode,3)),$(call int_encode,10))
+$(call test_assert,$(call int_divide,$(call int_encode,30),$(call int_encode,3)),$(call int_encode,10))
+$(call test_assert,$(call int_divide,$(call int_encode,29),$(call int_encode,3)),$(call int_encode,9))
+$(call test_assert,$(call int_divide,$(call int_encode,0),$(call int_encode,1)),$(call int_encode,0))
+$(call test_assert,$(call int_divide,$(call int_encode,1),$(call int_encode,0)),Division by zero)
+$(call stop_test)
+
+__gmsl_error = x x x x x x x x x x
+$(call start_test,divide)
+$(call test_assert,$(call divide,3,4),0)
+$(call test_assert,$(call divide,4,3),1)
+$(call test_assert,$(call divide,21,2),10)
+$(call test_assert,$(call divide,20,2),10)
+$(call test_assert,$(call divide,19,2),9)
+$(call test_assert,$(call divide,1,0),10)
+$(call stop_test)
+
+$(call start_test,associative array)
+$(call test_assert,$(call get,myarray,key1),)
+$(call set,myarray,key1,value1)
+$(call test_assert,$(call get,myarray,key1),value1)
+$(call test_assert,$(call get,myarray,key2),)
+$(call test_assert,$(call get,myarray1,key1),)
+$(call test_assert,$(call defined,myarray,key1),T)
+$(call test_assert,$(call defined,myarray,key2),)
+$(call test_assert,$(call defined,myarray1,key1),)
+$(call set,myarray,key2,value2)
+$(call test_assert,$(call keys,myarray),key1 key2)
+$(call test_assert,$(call keys,myarray1),)
+$(call stop_test)
+
+$(call start_test,named stack)
+$(call test_assert,$(call pop,mystack),)
+$(call test_assert,$(call push,mystack,e2))
+$(call push,mystack,e1)
+$(call test_assert,$(call pop,mystack),e1)
+$(call test_assert,$(call pop,mystack),e2)
+$(call push,mystack,f3)
+$(call push,mystack,f1)
+$(call test_assert,$(call pop,mystack),f1)
+$(call push,mystack,f2)
+$(call test_assert,$(call peek,mystack),f2)
+$(call test_assert,$(call depth,mystack),2)
+$(call test_assert,$(call pop,mystack),f2)
+$(call test_assert,$(call depth,mystack),1)
+$(call test_assert,$(call pop,myotherstack),)
+$(call stop_test)
+
+$(call start_test,reverse)
+$(call test_assert,$(call reverse,),)
+$(call test_assert,$(call reverse,1),1)
+$(call test_assert,$(call reverse,1 2),2 1)
+$(call test_assert,$(call reverse,1 2 3),3 2 1)
+$(call stop_test)
+
+$(call start_test,uniq)
+$(call test_assert,$(call uniq,),)
+$(call test_assert,$(call uniq,a),a)
+$(call test_assert,$(call uniq,a a),a)
+$(call test_assert,$(call uniq,a aa),a aa)
+$(call test_assert,$(call uniq,a aa a),a aa)
+$(call test_assert,$(call uniq,a b ba ab b a a ba a),a b ba ab)
+$(call stop_test)
+
+c:=,
+$(call start_test,split)
+$(call test_assert,$(call split,$c,comma$cseparated$cstring),comma separated string)
+$(call test_assert,$(call split,*,star*field*record),star field record)
+$(call test_assert,$(call split,*,star*),star)
+$(call test_assert,$(call split,*,star*field),star field)
+$(call test_assert,$(call split,*,star****field),star field)
+$(call test_assert,$(call split,*,),)
+$(call stop_test)
+
+$(call start_test,merge)
+$(call test_assert,$(call merge,$c,list of things),list$cof$cthings)
+$(call test_assert,$(call merge,*,list of things),list*of*things)
+$(call test_assert,$(call merge,*,list),list)
+$(call test_assert,$(call merge,*,),)
+$(call stop_test)
+
+$(call start_test,int_max)
+$(call test_assert,$(call int_max,$(call int_encode,2),$(call int_encode,1)),$(call int_encode,2))
+$(call test_assert,$(call int_max,$(call int_encode,1),$(call int_encode,2)),$(call int_encode,2))
+$(call test_assert,$(call int_max,$(call int_encode,2),$(call int_encode,0)),$(call int_encode,2))
+$(call test_assert,$(call int_max,$(call int_encode,0),$(call int_encode,2)),$(call int_encode,2))
+$(call test_assert,$(call int_max,$(call int_encode,2),$(call int_encode,2)),$(call int_encode,2))
+$(call test_assert,$(call int_max,$(call int_encode,0),$(call int_encode,0)),$(call int_encode,0))
+$(call stop_test)
+
+$(call start_test,max)
+$(call test_assert,$(call max,2,1),2)
+$(call test_assert,$(call max,1,2),2)
+$(call test_assert,$(call max,2,0),2)
+$(call test_assert,$(call max,0,2),2)
+$(call test_assert,$(call max,2,2),2)
+$(call test_assert,$(call max,0,0),0)
+$(call stop_test)
+
+$(call start_test,int_min)
+$(call test_assert,$(call int_min,$(call int_encode,2),$(call int_encode,1)),$(call int_encode,1))
+$(call test_assert,$(call int_min,$(call int_encode,1),$(call int_encode,2)),$(call int_encode,1))
+$(call test_assert,$(call int_min,$(call int_encode,2),$(call int_encode,0)),$(call int_encode,0))
+$(call test_assert,$(call int_min,$(call int_encode,0),$(call int_encode,2)),$(call int_encode,0))
+$(call test_assert,$(call int_min,$(call int_encode,2),$(call int_encode,2)),$(call int_encode,2))
+$(call test_assert,$(call int_min,$(call int_encode,0),$(call int_encode,0)),$(call int_encode,0))
+$(call stop_test)
+
+$(call start_test,min)
+$(call test_assert,$(call min,2,1),1)
+$(call test_assert,$(call min,1,2),1)
+$(call test_assert,$(call min,2,0),0)
+$(call test_assert,$(call min,0,2),0)
+$(call test_assert,$(call min,2,2),2)
+$(call test_assert,$(call min,0,0),0)
+$(call stop_test)
+
+__gmsl_error = $1
+$(call start_test,assert functions)
+$(call test_assert,$(call assert,$(true),ignore),)
+$(call test_assert,$(call assert,$(false),failed),Assertion failure: failed)
+$(call test_assert,$(call assert_exists,gmsl-tests),)
+$(call test_assert,$(call assert_exists,MISSING-gmsl-tests),Assertion failure: file 'MISSING-gmsl-tests' missing)
+$(call stop_test)
+
+$(call start_test,int_inc)
+$(call test_assert,$(call int_inc,$(call int_encode,0)),$(call int_encode,1))
+$(call test_assert,$(call int_inc,$(call int_encode,1)),$(call int_encode,2))
+$(call test_assert,$(call int_inc,$(call int_encode,4)),$(call int_encode,5))
+$(call test_assert,$(call int_inc,$(call int_encode,10)),$(call int_encode,11))
+$(call stop_test)
+
+$(call start_test,inc)
+$(call test_assert,$(call inc,0),1)
+$(call test_assert,$(call inc,1),2)
+$(call test_assert,$(call inc,4),5)
+$(call test_assert,$(call inc,10),11)
+$(call stop_test)
+
+__gmsl_warning = $1
+$(call start_test,int_dec)
+$(call test_assert,$(call int_dec,$(call int_encode,0)),Decrement underflow)
+$(call test_assert,$(call int_dec,$(call int_encode,1)),$(call int_encode,0))
+$(call test_assert,$(call int_dec,$(call int_encode,4)),$(call int_encode,3))
+$(call test_assert,$(call int_dec,$(call int_encode,10)),$(call int_encode,9))
+$(call stop_test)
+
+__gmsl_warning = x x x x x x x x x x
+$(call start_test,dec)
+$(call test_assert,$(call dec,0),10)
+$(call test_assert,$(call dec,1),0)
+$(call test_assert,$(call dec,4),3)
+$(call test_assert,$(call dec,10),9)
+$(call stop_test)
+
+$(call start_test,int_double)
+$(call test_assert,$(call int_double,$(call int_encode,0)),$(call int_encode,0))
+$(call test_assert,$(call int_double,$(call int_encode,1)),$(call int_encode,2))
+$(call test_assert,$(call int_double,$(call int_encode,4)),$(call int_encode,8))
+$(call stop_test)
+
+$(call start_test,double)
+$(call test_assert,$(call double,0),0)
+$(call test_assert,$(call double,1),2)
+$(call test_assert,$(call double,4),8)
+$(call stop_test)
+
+$(call start_test,int_halve)
+$(call test_assert,$(call int_halve,$(call int_encode,0)),$(call int_encode,0))
+$(call test_assert,$(call int_halve,$(call int_encode,2)),$(call int_encode,1))
+$(call test_assert,$(call int_halve,$(call int_encode,8)),$(call int_encode,4))
+$(call test_assert,$(call int_halve,$(call int_encode,7)),$(call int_encode,3))
+$(call stop_test)
+
+$(call start_test,halve)
+$(call test_assert,$(call halve,0),0)
+$(call test_assert,$(call halve,2),1)
+$(call test_assert,$(call halve,8),4)
+$(call test_assert,$(call halve,7),3)
+$(call stop_test)
+
+$(call start_test,gt)
+$(call test_assert,$(call gt,2,3),)
+$(call test_assert,$(call gt,3,2),$(true))
+$(call test_assert,$(call gt,2,2),)
+$(call stop_test)
+
+$(call start_test,gte)
+$(call test_assert,$(call gte,2,3),)
+$(call test_assert,$(call gte,3,2),$(true))
+$(call test_assert,$(call gte,2,2),$(true))
+$(call stop_test)
+
+$(call start_test,lt)
+$(call test_assert,$(call lt,2,3),$(true))
+$(call test_assert,$(call lt,3,2),)
+$(call test_assert,$(call lt,2,2),)
+$(call stop_test)
+
+$(call start_test,lte)
+$(call test_assert,$(call lte,2,3),$(true))
+$(call test_assert,$(call lte,3,2),)
+$(call test_assert,$(call lte,2,2),$(true))
+$(call stop_test)
+
+$(call start_test,eq)
+$(call test_assert,$(call eq,2,3),)
+$(call test_assert,$(call eq,3,2),)
+$(call test_assert,$(call eq,2,2),$(true))
+$(call stop_test)
+
+$(call start_test,ne)
+$(call test_assert,$(call ne,2,3),$(true))
+$(call test_assert,$(call ne,3,2),$(true))
+$(call test_assert,$(call ne,2,2),)
+$(call stop_test)
+
+$(call start_test,int_gt)
+$(call test_assert,$(call int_gt,$(call int_encode,2),$(call int_encode,3)),)
+$(call test_assert,$(call int_gt,$(call int_encode,3),$(call int_encode,2)),$(true))
+$(call test_assert,$(call int_gt,$(call int_encode,2),$(call int_encode,2)),)
+$(call stop_test)
+
+$(call start_test,int_gte)
+$(call test_assert,$(call int_gte,$(call int_encode,2),$(call int_encode,3)),)
+$(call test_assert,$(call int_gte,$(call int_encode,3),$(call int_encode,2)),$(true))
+$(call test_assert,$(call int_gte,$(call int_encode,2),$(call int_encode,2)),$(true))
+$(call stop_test)
+
+$(call start_test,int_lt)
+$(call test_assert,$(call int_lt,$(call int_encode,2),$(call int_encode,3)),$(true))
+$(call test_assert,$(call int_lt,$(call int_encode,3),$(call int_encode,2)),)
+$(call test_assert,$(call int_lt,$(call int_encode,2),$(call int_encode,2)),)
+$(call stop_test)
+
+$(call start_test,int_lte)
+$(call test_assert,$(call int_lte,$(call int_encode,2),$(call int_encode,3)),$(true))
+$(call test_assert,$(call int_lte,$(call int_encode,3),$(call int_encode,2)),)
+$(call test_assert,$(call int_lte,$(call int_encode,2),$(call int_encode,2)),$(true))
+$(call stop_test)
+
+$(call start_test,int_eq)
+$(call test_assert,$(call int_eq,$(call int_encode,2),$(call int_encode,3)),)
+$(call test_assert,$(call int_eq,$(call int_encode,3),$(call int_encode,2)),)
+$(call test_assert,$(call int_eq,$(call int_encode,2),$(call int_encode,2)),$(true))
+$(call stop_test)
+
+$(call start_test,int_ne)
+$(call test_assert,$(call int_ne,$(call int_encode,2),$(call int_encode,3)),$(true))
+$(call test_assert,$(call int_ne,$(call int_encode,3),$(call int_encode,2)),$(true))
+$(call test_assert,$(call int_ne,$(call int_encode,2),$(call int_encode,2)),)
+$(call stop_test)
+
+$(call start_test,gmsl_compatible)
+$(call test_assert,$(call gmsl_compatible,$(gmsl_version)),$(true))
+$(call test_assert,$(call gmsl_compatible,0 9 0),$(true))
+$(call test_assert,$(call gmsl_compatible,0 0 1),$(true))
+$(call test_assert,$(call gmsl_compatible,0 0 0),$(true))
+$(call test_assert,$(call gmsl_compatible,2 0 0),)
+$(call test_assert,$(call gmsl_compatible,1 1 0),)
+$(call test_assert,$(call gmsl_compatible,1 0 8),$(true))
+$(call test_assert,$(call gmsl_compatible,1 0 8),$(true))
+$(call test_assert,$(call gmsl_compatible,1 0 10),$(true))
+$(call test_assert,$(call gmsl_compatible,1 0 11),$(true))
+$(call test_assert,$(call gmsl_compatible,1 0 12),)
+$(call stop_test)
diff --git a/build/gmsl/index.html b/build/gmsl/index.html
new file mode 100644
index 0000000..8cc93ae
--- /dev/null
+++ b/build/gmsl/index.html
@@ -0,0 +1,687 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+ <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
+ <title>GNU Make Standard Library</title></head>
+
+<body>
+<h1>GNU Make Standard Library</h1>
+The GNU Make Standard Library (GMSL) is a collection of functions
+implemented using native GNU Make functionality that provide list and
+string manipulation, integer arithmetic, associative arrays, stacks,
+and debugging facilities.&nbsp; The GMSL is released under the BSD License.<br>
+<br>
+<a href="http://sourceforge.net/projects/gmsl/">[Project Page]</a> <a href="http://sourceforge.net/project/showfiles.php?group_id=129887">[Download]</a>
+<a href="http://sourceforge.net/forum/forum.php?forum_id=443916">[Discussion
+Forum]</a><br>
+<h2>Using GMSL</h2>
+The two files needed are <span style="font-family: monospace;">gmsl</span>
+and <span style="font-family: monospace;">__gmsl</span>.&nbsp; To
+include the GMSL in your Makefile do<br>
+<pre style="margin-left: 40px;">include gmsl</pre>
+<span style="font-family: monospace;">gmsl</span> automatically includes<span style="font-family: monospace;"> __gmsl</span>.&nbsp; To check that
+you have the right version of <span style="font-family: monospace;">gmsl</span>
+use the <span style="font-family: monospace;">gmsl_compatible</span>
+function (see
+below). The current version is <span style="font-family: monospace;">1
+0 11</span>.<br>
+<br>
+The GMSL package also includes a test suite for GMSL.&nbsp; Just run <span style="font-family: monospace;">make -f gmsl-tests</span>.<br>
+<h2>Logical Operators</h2>GMSL has boolean $(true) (a non-empty string)
+and $(false) (an empty string).&nbsp; The following operators can be
+used with those variables.<br>
+<br>
+<hr style="width: 100%; height: 2px;"><span style="font-weight: bold;">not</span><br>
+
+<br>
+
+<span style="font-family: monospace;">Arguments: A boolean value</span><br style="font-family: monospace;">
+
+<span style="font-family: monospace;">Returns:&nbsp;&nbsp; Returns $(true) if the boolean is $(false) and vice versa</span><br style="font-family: monospace;">
+
+<hr style="width: 100%; height: 2px; font-family: monospace;"><span style="font-weight: bold;"></span><span style="font-weight: bold;">and</span><br>
+<br>
+<span style="font-family: monospace;">Arguments: Two boolean values</span><br style="font-family: monospace;">
+<span style="font-family: monospace;">Returns:&nbsp;&nbsp; Returns $(true) if both of the booleans are true</span><br style="font-family: monospace;">
+<hr style="width: 100%; height: 2px; font-family: monospace;"><span style="font-weight: bold;">or</span><br>
+<br>
+<span style="font-family: monospace;">Arguments: Two boolean values</span><br style="font-family: monospace;">
+<span style="font-family: monospace;">Returns:&nbsp;&nbsp; Returns $(true) if either of the booleans is true</span><br style="font-family: monospace;">
+<hr style="width: 100%; height: 2px; font-family: monospace;"><span style="font-weight: bold;">xor</span><br style="font-weight: bold;">
+<br>
+<span style="font-family: monospace;">Arguments: Two boolean values</span><br style="font-family: monospace;">
+<span style="font-family: monospace;">Returns:&nbsp;&nbsp; Returns $(true) if exactly one of the booleans is true</span><br style="font-family: monospace;">
+<hr style="width: 100%; height: 2px; font-family: monospace;"><span style="font-weight: bold;">nand</span><br>
+<br>
+<span style="font-family: monospace;">Arguments: Two boolean values</span><br style="font-family: monospace;">
+<span style="font-family: monospace;">Returns:&nbsp;&nbsp; Returns value of 'not and'</span><br style="font-family: monospace;">
+<hr style="width: 100%; height: 2px; font-family: monospace;"><span style="font-weight: bold;">nor</span><br>
+<br>
+<span style="font-family: monospace;">Arguments: Two boolean values</span><br style="font-family: monospace;">
+<span style="font-family: monospace;">Returns:&nbsp;&nbsp; Returns value of 'not or'</span><br style="font-family: monospace;">
+<hr style="width: 100%; height: 2px; font-family: monospace;"><span style="font-weight: bold;">xnor</span><br>
+<br>
+<span style="font-family: monospace;">Arguments: Two boolean values</span><br style="font-family: monospace;">
+<span style="font-family: monospace;">Returns:&nbsp;&nbsp; Returns value of 'not xor'</span><br style="font-family: monospace;">
+<hr style="width: 100%; height: 2px; font-family: monospace;">
+<h2>List Manipulation Functions</h2>
+&nbsp;A list is a string of characters; the list separator is a space.<br>
+
+<br>
+<hr style="width: 100%; height: 2px;"><b>first</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A list<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the first element of a list<br>
+</span>
+<hr><b>last</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A list<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the last element of a list<br>
+</span>
+<hr><b>rest</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A list<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the list with the first element
+removed<br>
+</span>
+<hr><b>chop</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A list<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the list with the last element removed<br>
+</span>
+<hr><b>map</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: Name of function to
+$(call) for each element of list<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: List to
+iterate over calling the function in 1<br>
+Returns:&nbsp;&nbsp;&nbsp;The list after calling the function on each
+element<br>
+</span>
+<hr><b>pairmap</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: Name of function to
+$(call) for each pair of elements<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: List to
+iterate over calling the function in 1<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3: Second
+list to iterate over calling the function in 1<br>
+Returns:&nbsp;&nbsp;&nbsp;The list after calling the function on each
+pair of elements<br>
+</span>
+<hr><b>leq</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A list to compare
+against...<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: ...this
+list<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns $(true) if the two lists are identical<br>
+</span>
+<hr><b>lne</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A list to compare
+against...<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: ...this
+list<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns $(true) if the two lists are different<br>
+</span>
+<hr><b>reverse</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A list to reverse<br>
+Returns:&nbsp;&nbsp;&nbsp;The list with its elements in reverse order<br>
+</span>
+<hr><b>uniq</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A list to deduplicate<br>
+Returns:&nbsp;&nbsp;&nbsp;The list with elements in order without duplicates<br>
+</span>
+<hr><b>length</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A list<br>
+Returns:&nbsp;&nbsp;&nbsp;The number of elements in the list<br>
+</span>
+<hr style="width: 100%; height: 2px;"><span style="font-family: monospace;"></span>
+<h2>String Manipulation Functions</h2>
+A string is any sequence of characters.<br>
+<br>
+<hr style="width: 100%; height: 2px;"><b>seq</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A string to compare
+against...<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: ...this
+string<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns $(true) if the two strings are
+identical<br>
+</span>
+<hr><b>sne</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A string to compare
+against...<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: ...this
+string<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns $(true) if the two strings are not
+the same<br>
+</span>
+<hr><b>strlen</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A string<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the length of the string<br>
+</span>
+<hr><b>substr</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A string<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: Start offset (first character is 1)<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3: Ending offset (inclusive)<br>Returns:&nbsp;&nbsp;&nbsp;Returns a substring<br>
+</span>
+<hr><b>split</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: The character to
+split on<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: A
+string to split<br>
+Returns:&nbsp;&nbsp;&nbsp;Splits a string into a list separated by
+spaces at the split<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; character
+in the first argument<br>
+</span>
+<hr><b>merge</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: The character to
+put between fields<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: A list
+to merge into a string<br>
+Returns:&nbsp;&nbsp;&nbsp;Merges a list into a single string, list
+elements are separated<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by the
+character in the first argument<br>
+</span>
+<hr><b>tr</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: The list of
+characters to translate from <br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: The
+list of characters to translate to<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3: The
+text to translate<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the text after translating characters<br>
+</span>
+<hr><b>uc</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: Text to upper case<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the text in upper case<br>
+</span>
+<hr><b>lc</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: Text to lower case<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the text in lower case<br>
+</span>
+<hr style="width: 100%; height: 2px;"><span style="font-family: monospace;"></span>
+<h2>Set Manipulation Functions</h2>
+Sets are represented by sorted, deduplicated lists. To create a set
+from a list use <span style="font-family:
+monospace;">set_create</span>, or start with the <span
+style="font-family: monospace;">empty_set</span> and <span
+style="font-family: monospace;">set_insert</span> individual elements.
+The empty set is defined as <span style="font-family:
+monospace;">empty_set</span>.<p>
+
+<hr><b>set_create</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A list of set elements<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the newly created set<br>
+</span>
+
+<hr><b>set_insert</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A single element to add to a set<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2: A set<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the set with the element added<br>
+</span>
+
+<hr><b>set_remove</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A single element to remove from a set<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2: A set<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the set with the element removed<br>
+</span>
+
+<hr><b>set_is_member</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A single element<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2: A set<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns $(true) if the element is in the set<br>
+</span>
+
+<hr><b>set_union</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A set<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2: Another set<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the union of the two sets<br>
+</span>
+
+<hr><b>set_intersection</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A set<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2: Another set<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the intersection of the two sets<br>
+</span>
+
+<hr><b>set_is_subset</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A set<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2: Another set<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns $(true) if the first set is a subset of the second<br>
+</span>
+
+<hr><b>set_equal</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A set<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2: Another set<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns $(true) if the two sets are identical<br>
+</span>
+
+<hr style="width: 100%; height: 2px;"><span style="font-family: monospace;"></span>
+<h2>Integer Arithmetic Functions</h2>
+Integers are represented by lists with the equivalent number of
+x's.&nbsp; For example the number 4 is x x x x.&nbsp; The maximum
+integer that the library can handle as <span style="font-style: italic;">input</span> (i.e. as the argument to a
+call to <span style="font-family: monospace;">int_encode</span>) is
+65536. There is no limit on integer size for internal computations or
+output.<br>
+<br>
+The arithmetic library functions come in two forms: one form of each
+function takes integers as arguments and the other form takes the
+encoded form (x's created by a call to <span style="font-family: monospace;">int_encode</span>).&nbsp; For example,
+there are two plus functions: <span style="font-family: monospace;">plus</span>
+(called with integer arguments and returns an integer) and <span style="font-family: monospace;">int_plus</span> (called with encoded
+arguments and returns an encoded result).<br>
+<br>
+<span style="font-family: monospace;">plus</span> will be slower than <span style="font-family: monospace;">int_plus</span> because its arguments
+and result have to be translated between the x's format and
+integers.&nbsp; If doing a complex calculation use the <span style="font-family: monospace;">int_*</span> forms with a single
+encoding of inputs and single decoding of the output.&nbsp; For simple
+calculations the direct forms can be used.<br>
+<br>
+<hr style="width: 100%; height: 2px;"><b>int_decode</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A number of x's
+representation<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the integer for human consumption
+that is represented<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by the
+string of x's<br>
+</span>
+<hr><b>int_encode</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A number in
+human-readable integer form<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the integer encoded as a string of x's<br>
+</span>
+<hr><b>int_plus</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A number in x's
+representation<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: Another
+number in x's represntation<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the sum of the two numbers in x's
+representation<br>
+</span>
+<hr><b>plus (wrapped version of int_plus)</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: An integer<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: Another
+integer<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the sum of the two integers<br>
+</span>
+<hr><b>int_subtract</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A number in x's
+representation<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: Another
+number in x's represntation<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the difference of the two numbers in
+x's representation,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; or outputs
+an error on a numeric underflow<br>
+</span>
+<hr><b>subtract (wrapped version of int_subtract)</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: An integer<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: Another
+integer<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the difference of the two integers,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; or outputs
+an error on a numeric underflow<br>
+</span>
+<hr><b>int_multiply</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A number in x's
+representation<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: Another
+number in x's represntation<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the product of the two numbers in x's
+representation<br>
+</span>
+<hr><b>multiply (wrapped version of int_multiply)</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: An integer<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: Another
+integer<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the product of the two integers<br>
+</span>
+<hr><b>int_divide</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A number in x's
+representation<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: Another
+number in x's represntation<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the result of integer division of
+argument 1 divided<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by
+argument 2 in x's representation<br>
+</span>
+<hr><b>divide (wrapped version of int_divide)</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: An integer<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: Another
+integer<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the integer division of the first
+argument by the second<br>
+</span>
+<hr><b>int_max, int_min</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A number in x's
+representation<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: Another
+number in x's represntation<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the maximum or minimum of its
+arguments in x's<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+representation<br>
+</span>
+<hr><b>max, min</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: An integer<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: Another
+integer<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns the maximum or minimum of its integer
+arguments<br>
+</span>
+<hr><b>int_gt, int_gte, int_lt, int_lte, int_eq, int_ne</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: Two x's representation
+numbers to be compared<br>
+Returns:&nbsp;&nbsp;&nbsp;$(true) or $(false)<br>
+<br>
+int_gt First argument greater than second argument<br>
+int_gte First argument greater than or equal to second argument<br>
+int_lt First argument less than second argument <br>
+int_lte First argument less than or equal to second argument<br>
+int_eq First argument is numerically equal to the second argument<br>
+int_ne First argument is not numerically equal to the second argument<br>
+</span>
+<hr><b>gt, gte, lt, lte, eq, ne</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: Two integers to be
+compared<br>
+Returns:&nbsp;&nbsp;&nbsp;$(true) or $(false)<br>
+<br>
+gt First argument greater than second argument<br>
+gte First argument greater than or equal to second argument<br>
+lt First argument less than second argument <br>
+lte First argument less than or equal to second argument<br>
+eq First argument is numerically equal to the second argument<br>
+ne First argument is not numerically equal to the second argument<br>
+</span>
+increment adds 1 to its argument, decrement subtracts 1. Note that<br>
+decrement does not range check and hence will not underflow, but<br>
+will incorrectly say that 0 - 1 = 0<br>
+<hr><b>int_inc</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A number in x's
+representation<br>
+Returns:&nbsp;&nbsp;&nbsp;The number incremented by 1 in x's
+representation<br>
+</span>
+<hr><b>inc</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: An integer<br>
+Returns:&nbsp;&nbsp;&nbsp;The argument incremented by 1<br>
+</span>
+<hr><b>int_dec</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A number in x's
+representation<br>
+Returns:&nbsp;&nbsp;&nbsp;The number decremented by 1 in x's
+representation<br>
+</span>
+<hr><b>dec</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: An integer<br>
+Returns:&nbsp;&nbsp;&nbsp;The argument decremented by 1<br>
+</span>
+<hr><b>int_double</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A number in x's
+representation<br>
+Returns:&nbsp;&nbsp;&nbsp;The number doubled (i.e. * 2) and returned in
+x's representation<br>
+</span>
+<hr><b>double</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: An integer<br>
+Returns:&nbsp;&nbsp;&nbsp;The integer times 2<br>
+</span>
+<hr><b>int_halve</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A number in x's
+representation<br>
+Returns:&nbsp;&nbsp;&nbsp;The number halved (i.e. / 2) and returned in
+x's representation<br>
+</span>
+<hr><b>halve</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: An integer<br>
+Returns:&nbsp;&nbsp;&nbsp;The integer divided by 2<br>
+</span>
+<hr style="width: 100%; height: 2px;"><span style="font-family: monospace;"></span>
+<h2>Associative Arrays</h2>
+An associate array maps a key value (a string with no spaces in it) to
+a single value (any string).&nbsp;&nbsp;&nbsp; <br>
+<b><br>
+</b>
+<hr style="width: 100%; height: 2px;"><b>set</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: Name of associative
+array<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: The key
+value to associate<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3: The
+value associated with the key<br>
+Returns:&nbsp;&nbsp;&nbsp;None<br>
+</span>
+<hr><b>get</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: Name of associative
+array<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: The key
+to retrieve<br>
+Returns:&nbsp;&nbsp;&nbsp;The value stored in the array for that key<br>
+</span>
+<hr><b>keys</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: Name of associative
+array<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns a list of all defined keys in the
+array<br>
+</span>
+<hr><b>defined</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: Name of associative
+array<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: The key
+to test<br>
+Returns:&nbsp;&nbsp;&nbsp;Returns true if the key is defined (i.e. not
+empty)<br>
+</span>
+<hr style="width: 100%; height: 2px;"><span style="font-family: monospace;"></span>
+<h2>Named Stacks</h2>
+A stack is an ordered list of strings (with no spaces in them).<br>
+<br>
+<hr style="width: 100%; height: 2px;"><b>push</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: Name of stack<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: Value
+to push onto the top of the stack (must not contain<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a space)<br>
+Returns:&nbsp;&nbsp;&nbsp;None<br>
+</span>
+<hr><b>pop</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: Name of stack<br>
+Returns:&nbsp;&nbsp;&nbsp;Top element from the stack after removing it<br>
+</span>
+<hr><b>peek</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: Name of stack<br>
+Returns:&nbsp;&nbsp;&nbsp;Top element from the stack without removing it<br>
+</span>
+<hr><b>depth</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: Name of stack<br>
+Returns:&nbsp;&nbsp;&nbsp;Number of items on the stack<br>
+</span>
+<hr style="width: 100%; height: 2px;"><span style="font-family: monospace;"></span>
+<h2>Miscellaneous and Debugging Facilities</h2>
+GMSL defines the following constants; all are accessed as normal GNU
+Make variables by wrapping them in <span style="font-family: monospace;">$()</span> or <span style="font-family: monospace;">${}</span>.<br>
+<br>
+<table style="text-align: left;" border="1" cellpadding="2" cellspacing="2">
+ <tbody>
+ <tr>
+ <td><span style="font-style: italic;">Constant</span><br>
+ </td>
+ <td><span style="font-style: italic;">Value</span><br>
+ </td>
+ <td><span style="font-style: italic;">Purpose</span><br>
+ </td>
+ </tr>
+ <tr>
+ <td><span style="font-family: monospace;">true</span><br>
+ </td>
+ <td><span style="font-family: monospace;">T</span><br>
+ </td>
+ <td>Boolean for <span style="font-family: monospace;">$(if)</span>
+and return from&nbsp; GMSL functions<br>
+ </td>
+ </tr>
+ <tr>
+ <td><span style="font-family: monospace;">false</span><br>
+ </td>
+ <td><br>
+ </td>
+ <td>Boolean for <span style="font-family: monospace;">$(if)</span>
+and return from GMSL functions<br>
+ </td>
+ </tr>
+ <tr>
+ <td><span style="font-family: monospace;">gmsl_version</span><br>
+ </td>
+ <td><span style="font-family: monospace;">1 0 0</span><br>
+ </td>
+ <td>GMSL version number as list: major minor revision<br>
+ </td>
+ </tr>
+ </tbody>
+</table>
+<span style="font-weight: bold;"><br>
+gmsl_compatible</span><span style="font-family: monospace;"><br>
+<br>
+Arguments: List containing the desired library version number (maj min
+rev)<br>
+</span><span style="font-family: monospace;">Returns:&nbsp;&nbsp;
+$(true) if this version of the library is compatible<br>
+</span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+with the requested version number, otherwise $(false)</span>
+<hr><b>gmsl-print-% (target not a function)</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: The % should be
+replaced by the name of a variable that you<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wish to
+print out.<br>
+Action:&nbsp;&nbsp;&nbsp; Echos the name of the variable that matches
+the % and its value.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For
+example, 'make gmsl-print-SHELL' will output the value of<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the SHELL
+variable<br>
+</span>
+<hr><b>assert</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: A boolean that must
+be true or the assertion will fail<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: The
+message to print with the assertion<br>
+Returns:&nbsp;&nbsp;&nbsp;None<br>
+</span>
+<hr><b>assert_exists</b><br>
+<br>
+<span style="font-family: monospace;">Arguments: 1: Name of file that
+must exist, if it is missing an assertion<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; will be
+generated<br>
+Returns:&nbsp;&nbsp;&nbsp;None<br>
+</span>
+<hr style="width: 100%; height: 2px;"><br>
+GMSL has a number of environment variables (or command-line overrides)
+that control various bits of functionality:<br>
+<br>
+<table style="text-align: left;" border="1" cellpadding="2" cellspacing="2">
+ <tbody>
+ <tr>
+ <td><span style="font-style: italic;">Variable</span><br>
+ </td>
+ <td><span style="font-style: italic;">Purpose</span><br>
+ </td>
+ </tr>
+ <tr>
+ <td><span style="font-family: monospace;">GMSL_NO_WARNINGS</span><br>
+ </td>
+ <td>If set prevents GMSL from outputting warning messages:
+artithmetic functions generate underflow warnings.<br>
+ </td>
+ </tr>
+ <tr>
+ <td><span style="font-family: monospace;">GMSL_NO_ERRORS</span><br>
+ </td>
+ <td>If set prevents GMSL from generating fatal errors: division
+by zero or failed assertions are fatal.<br>
+ </td>
+ </tr>
+ <tr>
+ <td><span style="font-family: monospace;">GMSL_TRACE</span><br>
+ </td>
+ <td>Enables function tracing.&nbsp; Calls to GMSL functions will
+result in name and arguments being traced.<br>
+ </td>
+ </tr>
+ </tbody>
+</table>
+<span style="font-family: monospace;"></span><br>
+<hr>
+Copyright (c) 2005-2006 <a href="http://www.jgc.org/">John Graham-Cumming</a>.<br>
+<hr style="width: 100%; height: 2px;">
+<table style="width: 100%; text-align: left;" border="0" cellpadding="2" cellspacing="2">
+ <tbody>
+ <tr>
+ <td style="width: 50%;">John Graham-Cumming's work on this
+project was sponsored by <a href="http://www.electric-cloud.com/">Electric
+Cloud, Inc</a>.<br>
+ <a href="http://www.electric-cloud.com/"><img alt="" src="http://gmsl.sf.net/ec_logo.gif" style="border: 0px solid ; width: 223px; height: 47px;"></a><br>
+ </td>
+ <td align="right">
+ <p><a href="http://sourceforge.net/"><img src="http://sourceforge.net/sflogo.php?group_id=129887&amp;type=1" alt="SourceForge.net Logo" border="0" height="31" width="88"></a></p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</body></html>
diff --git a/platforms/android-portable/arch-llvm/usr/include/test.h b/platforms/android-portable/arch-llvm/usr/include/test.h
deleted file mode 100644
index e69de29..0000000
--- a/platforms/android-portable/arch-llvm/usr/include/test.h
+++ /dev/null
diff --git a/samples/bitmap-plasma-llvm/jni/Application.mk b/samples/bitmap-plasma-llvm/jni/Application.mk
index 8c85307..59fdfab 100644
--- a/samples/bitmap-plasma-llvm/jni/Application.mk
+++ b/samples/bitmap-plasma-llvm/jni/Application.mk
@@ -1,3 +1,3 @@
# The ARMv7 is significanly faster due to the use of the hardware FPU
APP_ABI := armeabi armeabi-v7a
-APP_PLATFORM := android-8
+APP_PLATFORM := android-12
diff --git a/samples/bitmap-plasma-llvm/res/raw/armeabi-v7a/gdb.setup b/samples/bitmap-plasma-llvm/res/raw/armeabi-v7a/gdb.setup
new file mode 100644
index 0000000..d7abec1
--- /dev/null
+++ b/samples/bitmap-plasma-llvm/res/raw/armeabi-v7a/gdb.setup
@@ -0,0 +1,2 @@
+set solib-search-path /home/nowar/cyanogen/gdk/samples/bitmap-plasma-llvm/obj/local/armeabi-v7a
+directory /home/nowar/cyanogen/gdk/platforms/android-9/arch-arm/usr/include /home/nowar/cyanogen/gdk/samples/bitmap-plasma-llvm/jni /home/nowar/cyanogen/gdk/sources/cxx-stl/system
diff --git a/samples/bitmap-plasma-llvm/res/raw/armeabi-v7a/gdbserver b/samples/bitmap-plasma-llvm/res/raw/armeabi-v7a/gdbserver
new file mode 100755
index 0000000..39634a8
--- /dev/null
+++ b/samples/bitmap-plasma-llvm/res/raw/armeabi-v7a/gdbserver
Binary files differ
diff --git a/samples/bitmap-plasma-llvm/res/raw/armeabi/gdb.setup b/samples/bitmap-plasma-llvm/res/raw/armeabi/gdb.setup
new file mode 100644
index 0000000..d549cf4
--- /dev/null
+++ b/samples/bitmap-plasma-llvm/res/raw/armeabi/gdb.setup
@@ -0,0 +1,2 @@
+set solib-search-path /home/nowar/cyanogen/gdk/samples/bitmap-plasma-llvm/obj/local/armeabi
+directory /home/nowar/cyanogen/gdk/platforms/android-9/arch-arm/usr/include /home/nowar/cyanogen/gdk/samples/bitmap-plasma-llvm/jni /home/nowar/cyanogen/gdk/sources/cxx-stl/system
diff --git a/samples/bitmap-plasma-llvm/res/raw/armeabi/gdbserver b/samples/bitmap-plasma-llvm/res/raw/armeabi/gdbserver
new file mode 100755
index 0000000..39634a8
--- /dev/null
+++ b/samples/bitmap-plasma-llvm/res/raw/armeabi/gdbserver
Binary files differ
diff --git a/samples/bitmap-plasma-llvm/res/raw/gdb.setup b/samples/bitmap-plasma-llvm/res/raw/gdb.setup
new file mode 100644
index 0000000..d7abec1
--- /dev/null
+++ b/samples/bitmap-plasma-llvm/res/raw/gdb.setup
@@ -0,0 +1,2 @@
+set solib-search-path /home/nowar/cyanogen/gdk/samples/bitmap-plasma-llvm/obj/local/armeabi-v7a
+directory /home/nowar/cyanogen/gdk/platforms/android-9/arch-arm/usr/include /home/nowar/cyanogen/gdk/samples/bitmap-plasma-llvm/jni /home/nowar/cyanogen/gdk/sources/cxx-stl/system
diff --git a/samples/bitmap-plasma-llvm/res/raw/gdbserver b/samples/bitmap-plasma-llvm/res/raw/gdbserver
new file mode 100755
index 0000000..39634a8
--- /dev/null
+++ b/samples/bitmap-plasma-llvm/res/raw/gdbserver
Binary files differ
diff --git a/toolchains/llvm/config.mk b/toolchains/llvm/config.mk
new file mode 100644
index 0000000..c880834
--- /dev/null
+++ b/toolchains/llvm/config.mk
@@ -0,0 +1 @@
+TOOLCHAIN_ABIS := llvm
diff --git a/toolchains/llvm/setup.mk b/toolchains/llvm/setup.mk
index 6b47802..074ab94 100644
--- a/toolchains/llvm/setup.mk
+++ b/toolchains/llvm/setup.mk
@@ -1,29 +1,26 @@
-GDK_TOOLCHAIN_PREFIX := $(GDK_TOOLCHAIN_ROOT)/llvm/prebuilt/
-
-# FIXME(Nowar): In future, we use llvm-ndk-cc and llvm-ndk-link.
-#BITCODE_CC := $(GDK_TOOLCHAIN_PREFIX)llvm-ndk-cc
-#BITCODE_CFLAGS :=
+# FIXME(Nowar): Use llvm-ndk-cc instead of clang.
+#TARGET_CC := $(TOOLCHAIN_PREBUILT_ROOT)/llvm-ndk-cc
+#TARGET_CFLAGS :=
#
-#BITCODE_CPP := $(GDK_TOOLCHAIN_PREFIX)llvm-ndk-cc
-#BITCODE_CPPFLAGS := $(BITCODE_CFLAGS) -fno-exceptions -fno-rtti -D __cplusplus
+#TARGET_CXX := $(TARGET_CC)
+#TARGET_CXXFLAGS := $(TARGET_CFLAGS) -fno-exceptions -fno-rtti -D __cplusplus
#
-#BITCODE_LD := $(GDK_TOOLCHAIN_PREFIX)llvm-ndk-link
-#BITCODE_LDFLAGS :=
+#TARGET_LD := $(TOOLCHAIN_PREBUILT_ROOT)/llvm-ndk-link
+#TARGET_LDFLAGS :=
+
+TARGET_C_INCLUDES := $(GDK_PLATFORMS_ROOT)/android-portable/arch-llvm/usr/include
+
+TARGET_CC := clang
+TARGET_CFLAGS := -ccc-host-triple armv7-none-linux-gnueabi -emit-llvm
-BITCODE_CC := clang
-BITCODE_CFLAGS := -ccc-host-triple armv7-none-linux-gnueabi -emit-llvm
-BITCODE_CPP := clang++
-BITCODE_CPPFLAGS := $(BITCODE_CFLAGS) -fno-exceptions -fno-rtti -D __cplusplus
-BITCODE_LD := llvm-link
-BITCODE_LDFLAGS :=
+TARGET_CXX := clang++
+TARGET_CXXFLAGS := $(TARGET_CFLAGS) -fno-exceptions -fno-rtti -D __cplusplus
-BITCODE_C_INCLUDES := \
- $(GDK_PLATFORM_ROOT)/usr/include
+TARGET_LD := llvm-link
+TARGET_LDFLAGS :=
-#define cmd-build-bitcode
-#$(BITCODE_LD) \
-# $(call host-path, $(PRIVATE_OBJECTS)) \
-# $(PRIVATE_LDFLAGS) \
-# $(PRIVATE_LDLIBS) \
-# -o $(call host-path, $@)
-#endef
+define cmd-link-bitcodes
+$(TARGET_LD) \
+ $(call host-path, $(PRIVATE_OBJECTS)) \
+ -o $(call host-path,$@)
+endef