Tag: Programming

  • From Lines to Neurons

    From Lines to Neurons

    A statement that has been circulating on Twitter recently:

    “Thinking can be outsourced. Understanding cannot.”

    An understanding of Engineering fundamentals will remain valuable, even as LLMs’ growing ability to generate plausible code and text.

    Start with linear regression

    Neural networks approximate functions.

    Linear regression is the simplest mathematical approach to achieve the same. A cloud of points and an infinite number of lines. What is the best-fitting line among them? The one where the distance between its predictions and the actual points is minimum.

    That distance has a name: the loss. Linear regression fits the line by minimizing it. Pick weights → measure the loss → adjust → repeat.

    Neural networks build on the same concept.

    A neuron is just a line, bent

    Linear regression can only fit straight lines. Real data isn’t straight.

    A neuron takes w · x + b and runs the result through a curved function (a sigmoid). That single bend is the entire upgrade. Now you can fit S-curves. Stack two neurons and you can fit bumps. Stack thousands across many layers and you can fit anything.

    The training algorithm is the same as linear regression: gradient descent. The only addition is backpropagation — the chain rule from calculus, applied backwards to figure out how each weight contributes to the loss.

    Scale this up

    Stack thousands of these neurons. Add an attention mechanism so each neuron dynamically picks which inputs from the previous layer to care about. Train on the internet.

    You get GPT. We will dive deeper into that in my next post.


    Full interactive guide with the live code and a training playground:

    Neural Networks: From Lines to Neurons

  • Is Software Solved?

    Is Software Solved?

    In 2011, Marc Andreessen declared that software is eating the world. Fifteen years later, the question has flipped: something is eating software itself, and that something is AI.

    Writing code has become too cheap; this is a fact. Code is a formal language, and LLMs — since the 2017 “Attention Is All You Need” paper — have learned the whole internet by heart. They can dream text, which sounds convincing and is not wrong in most cases, and they can speak multiple languages.

    I, a PM who hadn’t written real code for years, worked through the last few months on 4 projects at different complexity levels. 2 of them were within my company, and one is running just fine in the production pipeline.

    The demand for code is clearly going up, and economics tells us why. When a good becomes cheaper, demand for it increases. As an analogy: cameras got radically cheaper and better; everyone has one; photos are infinite and near-free. People are still buying more cameras and taking more photos — and good photographers are more valuable than ever.

    Software ≠ Code. Software is a solution that runs on a computer; this solution needs to have a purpose. Identifying the purpose is hard; often, neither the customer nor the dev teams know what to build. Along the way, frameworks and best practices were developed to define clearly and, most importantly, align on what to build.

    The solution then needs to be coded in a way that the computer understands; it can be done in spaghetti style or using clean code. In both cases, the solution will serve its purpose, but in the former case, it will fail the test of time quickly, depending on how bad the code is. Smart engineers spent decades inventing ways to make solutions maintainable: testing, design patterns, static code analysis — you name it.

    All those activities and artifacts are complementary to the code; code cannot live in a vacuum. To have meaningful software, they are needed as well. They didn’t get cheaper, though. Copilot won’t help you build the right thing faster. On the contrary, it helps you build many wrong things faster. Call it a diversion, or call it fast prototyping.

    Those complements will become more expensive in my opinion, or at least economic theory tells us so. If there is a huge demand for cars in one city, tires become more expensive, not cheaper. Morgan Stanley analysts recently made a similar point: as code generation gets cheap, the scarce inputs shift elsewhere — to data, to judgment, to the specification of what is actually worth building.

    We are in the middle of the euphoria and shock, still wrapping our heads around how the computer can one-shot code that used to take weeks to write. But that’s not software development. The craft still matters, and will matter even more.

  • Setting up Rust Environment for Linux Kernel Development

    Setting up Rust Environment for Linux Kernel Development

    Hey 👋

    It’s me again, still writing about Rust before actually going beyond the hello world part of the documentation, but I will let you know why.

    I am currently going through Chris Simmonds’ terrific book “Mastering Embedded Linux Programming, and while reading through the chapter covering the kernel configuration and compilation , I stumbled upon a nice youtube video from the linux foundation covering the same topic but using the Rust fork as the codebase.

    So, since I have an interest in Rust too, I said why not combining both ? Which was actually a good choice because both the video and the book covered each other gaps.

    While watching the video, I took a note of most of the commands in a github gist which I think should be pretty useful for my future self and and other people too. I thought also of taking the notes here because why not ..

    #
    # Instructions for the video https://www.youtube.com/watch?v=tPs1uRqOnlk excluding setting up the env ( e.g. installing Rust and llvm)
    #
    
    
    #
    # Kernel
    #
    
    $ git clone --depth=1 https://github.com/Rust-for-Linux/linux.git
    $ cd linux/
    $ make allnoconfig qemu-busybox-min.config
    $ make allnoconfig qemu-busybox-min.config rust.config
    $ make LLVM=1 rustavailable # should say Rust is available if you have all dependencies
    $ make LLVM=1 -j4
    
    #
    # Busybox
    #
    $ cd busybox
    $ git clone --depth=1 https://github.com/mirror/busybox.git
    $ make defconfig
    $ make menuconfig # then from settings select use static libraries 
    # make -j4
    $ cd ./_install/
    $ find . | cpio -H newc -o | gzip > ../ramdisk.img
    
    
    #
    # running qemu
    #
    $ cd linux/
    $ qemu-system-x86_64 -nographic -kernel vmlinux # should panic
    $ qemu-system-x86_64 -nographic -kernel vmlinux -initrd ../busybox/ramdisk.img # should start
    
    
    #
    # adding proc filesystem to enable ps
    #
    $ cd busybox/_install/
    $ vim etc/init.d/rcS 
    # then add this content inside 
    # mkdir -p /proc 
    # mount -t proc none /proc
    $ find . | cpio -H newc -o | gzip > ../ramdisk.img
    $ qemu-system-x86_64 -nographic -kernel vmlinux -initrd ../busybox/ramdisk.img # ps should work
    
    
    #
    # enabling a rust sample kernel module
    #
    $ make LLVM=1 menuconfig
    # then select the samples from kernel hacking --> samples --> rust samples
    
    
    #
    # enable networking
    #
    $ cd busybox/_install/
    $ vim etc/init.d/rcS 
    # then add this content inside to enable loopback interface 
    # ifconfig lo up
    # udhcpc -i eth0
    $ mkdir -p usr/share/udhcpc
    $ cp ../examples/udhcp/simple.script usr/share/udhcpc/default.script
    $ qemu-system-x86_64 -nographic -kernel vmlinux -initrd ../busybox/ramdisk.img -nic user,model=rtl8139
    $ qemu-system-x86_64 -nographic -kernel vmlinux -initrd ../busybox/ramdisk.img -nic user,model=rtl8139,hostfwd=tcp::5556-:8080

  • How to downgrade Rust compiler to a specific version ?

    How to downgrade Rust compiler to a specific version ?

    Hi !

    There are a couple of pages/stackoverflow questions which mention how to install a specific Rust version which is pretty straightforward using rustup install command

    abdelah@abdelah-VirtualBox:~/workspace/linux$ rustup install 1.62.0
    info: syncing channel updates for '1.62.0-x86_64-unknown-linux-gnu'
    info: latest update on 2022-06-30, rust version 1.62.0 (a8314ef7d 2022-06-27)
    ....

    However, there is one tiny step also needed to set the default compiler to the newly installed version, for instance if you run the command above and invoke rustc --version you would still get the previously installed default version.

    abdelah@abdelah-VirtualBox:~/workspace/linux$ rustc --version
    rustc 1.66.1 (90743e729 2023-01-10)

    I am pretty new to Rust ( haven’t read the hello world example fully yet to be honest ), but I already like how the commands come intuitively to mind opposed to other popular tools such as git (always scratched my head trying variants of git checkout and git reset to clean a working directory )

    So, back to topic. Now we need to set the default compiler version to 1.62.0, for that we just need to execute rustup deault my-preferred-version but first we can get the list of installed versions like this

    abdelah@abdelah-VirtualBox:~/workspace/linux$ rustup toolchain list
    stable-x86_64-unknown-linux-gnu (default)
    1.62.0-x86_64-unknown-linux-gnu

    Then set the default version

    abdelah@abdelah-VirtualBox:~/workspace/linux$ rustup default 1.62.0-x86_64-unknown-linux-gnu
    info: using existing install for '1.62.0-x86_64-unknown-linux-gnu'
    info: default toolchain set to '1.62.0-x86_64-unknown-linux-gnu'
    
      1.62.0-x86_64-unknown-linux-gnu unchanged - rustc 1.62.0 (a8314ef7d 2022-06-27)

    Now, let’s do a smoke test on the compiler version

    abdelah@abdelah-VirtualBox:~/workspace/linux$ rustc --version
    rustc 1.62.0 (a8314ef7d 2022-06-27)

    Okay, this works now !

    You might be wondering what would be a usecase for using a specific older compiler version, well my answer to this would be this snippet from Rust documentation in the Linux kernel

    rustc
    *****
    
    A particular version of the Rust compiler is required. Newer versions may or may not work because, for the moment, the kernel depends on some unstable
    Rust features.
    

    Starting Linux kernel release v6.1, Rust support was introduced and this grabbed my attention as Rust is claimed to be safer and more secure than C/C++. Safety and Security are two words that one would hear everyday if you work at any company producing or contributing to the production of passenger cars.

    I wanted to have a look and play around a bit and then to test if my environment is ready to build Rust in the kernel

    abdelah@abdelah-VirtualBox:~/workspace/linux$ make LLVM=1 rustavailable
    ***
    *** Rust compiler 'rustc' is too new. This may or may not work.
    ***   Your version:     1.66.1
    ***   Expected version: 1.62.0
    ***
    Rust is available!

    And because I wouldn’t take may or may not work as an answer, I downgraded my compiler version.

  • Relating C++ move semantics to python objects

    I have been learning lately about C++11 move semantics, originally being a C programmer who is concerned with the performance it was very interesting to explore such an important optimization feature. I had to go through many articles explaining rvalues, lvalues and the && operator. I believe you still need to learn these topics to develop a firm understanding of the topic but in my point of view the move semantics can be explained intuitively by drawing the similarity between it and python’s object execution model.

    The goal of move semantics is to avoid copying large objects unnecessarily when they are passed from one function to another.

    How are objects passed in python?

    Interestingly enough, python was created with that particular optimization in mind.

    Firstly, It’s important to understand the subtle difference between the interpretation of the following statement in python and C++


    str = 'medium'

    view raw

    assignment.py

    hosted with ❤ by GitHub

    In C++ the variable str is created in memory, this location in memory contains the data medium and str refers to this memory location.

    However in python the story is different. Although this statement also creates an object with the same content, but str isn’t the object reference. str is a merely a name and the statement binds it to the object. This subtle deviation may not look crucial but it makes all the difference when passing arguments to a function.

    Consider the following 2 code snippets


    def modify(arg):
    arg = 'hard'
    str = 'medium'
    modify(str)
    print(str) # >> medium

    In the first snippet, an immutable object is created containing the data ‘medium’ and str is bound to this object. When the method modify is called a new name arg is also bound to ‘medium’, but as soon as line 2 is executed the binding of arg is relocated to another new object with the data ‘hard’ because there is no way to change an immutable. The resulting behavior appears as a conventional pass by value call.


    def modify(arg):
    arg += [1]
    l = [2]
    modify(l)
    print(l) # >> [2, 1]

    view raw

    call-by-ref.py

    hosted with ❤ by GitHub

    On the other hand, the behavior depicted in the second snippet resembles a pass by reference call as modify here doesn’t rebind arg to a new object because this object is mutable. arg and l are two names bound to the same object. When line 2 is executed this object is modified.

    In python object references are passed by value, in other words objects are moved.

    C++ move semantics in layman terms

    Before the move semantics there were a couple of ways to avoid unnecessary large copies by passing pointers around which is somehow considered an unsafe practice compared to use an instantiated object which auto destructs.

    Move semantics are based on rvalue references. An rvalue appears on the right hand side of the assignment statement. Example of an rvalue could be “medium” here:


    string str = "medium";

    view raw

    assignment.cpp

    hosted with ❤ by GitHub

    Also the function getName() can return an rvalue because it appears on the right side of the statement.


    string getName() {
    string str = "medium";
    return s;
    }
    // getName() returns an rvalue
    string&& name = getName();

    view raw

    rvalue.cpp

    hosted with ❤ by GitHub

    name is an rvalue reference.

    I like to think of an rvalue as a python object and the rvalue reference as the name bound to this object. The difference being that an rvalue can’t exist on its own while python relies on garbage collection to clean up objects which are no longer bound to any scope.


    class Obj {
    //default constructor
    Obj(int size){
    ..
    }
    //copy constructor
    Obj(const Obj& other){
    ..
    }
    //assignment operator
    Obj& operator= (const Obj& other){
    ..
    }
    }
    Obj B;
    B = Obj(1000);

    view raw

    copy.cpp

    hosted with ❤ by GitHub

    Without a move constructor the last line assignment will

    • allocate memory for the temporary object (and destruct it later)
    • allocate memory again at the destination

    Adding a move constructor to the object definition will optimize out the second allocation and reuse the previous allocation for the destination.


    class Obj {
    //move constructor
    Obj(const Obj&& other){
    ..
    }
    //move assignment operator
    Obj& operator= (const Obj&& other){
    ..
    }
    }

    view raw

    move.cpp

    hosted with ❤ by GitHub

    Conclusion

    Having this analogy in head, comprehending the power of move semantics was no more complicated. When a move constructor is defined for an object, it will be possible to rebind it to different name while avoiding expensive copies.

    Resources

    https://medium.com/@meghamohan/mutable-and-immutable-side-of-python-c2145cf72747

    https://www.internalpointers.com/post/c-rvalue-references-and-move-semantics-beginners

    Lesson #5: Move Semantics

    https://stackoverflow.com/questions/3106110/what-is-move-semantics

     

  • Android Build System Ultimate Guide

    Android Build System Ultimate Guide

    Lately, Android Open Source Project has gone through various changes. For instance, Since JB Google decided to replace bluez bluetooth stack with an open source stack implemented by Broadcom claiming that the later is more optimized for Android devices causing a headache and new bugs for many users and developers, also there are frequent architectural changes (for example : the HAL layer) and so on… 

    The one fact that proved not to change through Android Open Source project lifetime is that it’s documentation is very poor and that was the main reason for me compiling this document from various blogs, android docs (which are gratefully referred to at the end of the page) and my own experience trying to produce as complete document as possible for the Android Build System including steps to build the source tree , some build tricks and hints!

    Also, I tried to answer the famous question : “How do I add a java (or native) application into my android build ?

    I hope this post shall be useful 🙂

    Table Of Contents

    Overview

    The build system uses some pre-set environment variables and a series of ‘make’ files in order to build an Android system and prepare it for deployment to a platform.

    Android make files end in the extension ‘.mk’ by convention, with the main make file in any particular source directory being named ‘Android.mk’.
    There is only one official file named ‘Makefile’, at the top of the source tree for the whole repository. You set some environment variables, then type ‘make’ to build stuff. You can add some options to the make command line (other targets) to turn on verbose output, or perform different actions.

    The build output is placed in ‘out/host’ and ‘out/target’ Stuff under ‘out/host’ are things compiled for your host platform (your desktop machine). Stuff under ‘out/target/product/<platform-name>’ eventually makes it’s way to a target device (or emulator).

    The directory ‘out/target/product/<platform-name>/obj’ is used for staging “object” files, which are intermediate binary images used for building the final programs. Stuff that actually lands in the file system of the target is stored in the directories root, system, and data, under ‘out/target/product/<platform-name>’. Usually, these are bundled up into image files called system.img, ramdisk.img, and userdata.img.
    This matches the separate file system partitions used on most Android devices.


    Building Steps

    In order to decide what to build, and how to build it, the build system requires that some variables be set. Different products, with different packages and options can be built from the same source tree. The variables to control this can be set via a file with declarations of ‘make’ variables, or can be specified in the environment.

    envsetup

    To set up your build environment, you need to load the variables and functions in build/envsetup.sh. Do this by ‘source-ing’ the file into your shell environment, like this:

    $ source build/envsetup.sh

    or

    $ . build/envsetup.sh

    You can type

    $ hmm

    at this point to see some utility functions that are available to make it easier to work with the source.

    Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
    - lunch:   lunch <product_name>-<build_variant>
    - tapas:   tapas [<App1> <App2> ...] [arm|x86|mips] [eng|userdebug|user]
    - croot:   Changes directory to the top of the tree.
    - m:       Makes from the top of the tree.
    - mm:      Builds all of the modules in the current directory.
    - mmm:     Builds all of the modules in the supplied directories.
    - cgrep:   Greps on all local C/C++ files.
    - jgrep:   Greps on all local Java files.
    - resgrep: Greps on all local res/*.xml files.
    - godir:   Go to the directory containing a file.
    
    Look at the source to view more functions. The complete list is:
    addcompletions add_lunch_combo cgrep check_product check_variant choosecombo chooseproduct choosetype choosevariant cproj croot findmakefile gdbclient
    get_abs_build_var getbugreports get_build_var getlastscreenshot getprebuilt getscreenshotpath getsdcardpath gettargetarch gettop godir hmm 
    isviewserverstarted jgrep key_back key_home key_menu lunch _lunch m mm mmm pid printconfig print_lunch_menu resgrep runhat runtest set_java_home 
    setpaths set_sequence_number set_stuff_for_environment settitle smoketest startviewserver stopviewserver systemstack tapas tracedmdump

    choosing target

    To select the set of things you want to build, and what items to build for, you use either the ‘choosecombo’ function or the ‘lunch’ function. ‘choosecombo’ will walk you through the different items you have to select, one-by-one, while ‘lunch’ allows you select some pre-set combinations.
    The items that have to be defined for a build are:
    the product (‘generic’ or some specific board or platform name)
    the build variant (‘user’, ‘userdebug’, or ‘eng’)
    whether you’re running on a simulator (‘true’ or ‘false’)
    the build type (‘release’ or ‘debug’)


    Building Tricks

    Seeing the actual commands used to build the software

    Use the “showcommands” target on your ‘make’ line:

    $ make -j4 showcommands

    This can be used in conjunction with another make target, to see the commands for that build. That is, ‘showcommands’ is not a target itself, but just a modifier for the specified build.
    In the example above, the -j4 is unrelated to the showcommands option, and is used to execute 4 make sessions that run in parallel.

    Make targets

    Here is a list of different make targets you can use to build different parts of the system:

    make sdk - build the tools that are part of an SDK (adb, fastboot, etc.)
    make snod - build the system image from the current software binaries
    make services
    make runtime
    make droid - make droid is the normal build.
    make all - make everything, whether it is included in the product definition or not
    make clean - remove all built files (prepare for a new build). Same as rm -rf out/<configuration>/
    make modules - shows a list of submodules that can be built (List of all LOCAL_MODULE definitions)
    make <local_module> - make a specific module (note that this is not the same as directory name. It is the LOCAL_MODULE definition in the Android.mk file)
    make clean-<local_module> - clean a specific module

    Speeding up the build

    You can use the ‘-j’ option with make, to start multiple threads of make execution concurrently.
    You can also specify to use the ‘ccache’ compiler cache, which will speed up things once you have built things a first time. To do this, specify ‘export USE_CCACHE=1’ at your shell command line. (Note that ccache is included in the prebuilt section of the repository, and does not have to be installed on your host separately.)

    Building only an individual program or module

    If you use build/envsetup.sh, you can use some of the defined functions to build only a part of the tree. Use the ‘mm’ or ‘mmm’ commands to do this.
    The ‘mm’ command makes stuff in the current directory (and sub-directories, I believe). With the ‘mmm’ command, you specify a directory or list of directories, and it builds those.

    Build helper functions

    A whole bunch of build helper functions are defined in the file build/core/definitions.mk
    Try grep define build/core/definitions.mk for an exhaustive list.
    Here is a snapshot of the file

    ###########################################################
    ## Find all of the java files from here.  Meant to be used like:
    ##    SRC_FILES := $(call all-subdir-java-files)
    ###########################################################
    
    define all-subdir-java-files
    $(call all-java-files-under,.)
    endef
    
    ###########################################################
    ## Find all of the c files under the named directories.
    ## Meant to be used like:
    ##    SRC_FILES := $(call all-c-files-under,src tests)
    ###########################################################
    
    define all-c-files-under
    $(patsubst ./%,%, \
      $(shell cd $(LOCAL_PATH) ; \
              find $(1) -name "*.c" -and -not -name ".*") \
     )
    endef
    

    Build System Architecture

    to be added….


    How to add another component to the build

    It’s simple to add a new java or native application to your android build , you just

    1. create the directory and copy your src files to it.
    2. then you should add the appropriate Android.mk file, the next section will help you to understand Android.mk files and write your own makefile.
    3. build the image and flash it to your device.

    Template Android.mk files

    • Executable Template
    LOCAL_PATH:= $(call my-dir)   # call function my-dir will return the path of Android.mk
    include $(CLEAR_VARS)         # clean all variables mainly started with LOCAL_
    
    LOCAL_SRC_FILES:= foo.c       # Source file list
    LOCAL_MODULE:= foo            # The name of executable binary
    
    include $(BUILD_EXECUTABLE)   # Start to build executable binary
    • Shared Library Template
    LOCAL_PATH:= $(call my-dir)     # call function my-dir will return the path of Android.mk
    include $(CLEAR_VARS)           # clean all variables mainly started with LOCAL_
    
    LOCAL_SRC_FILES:= foo.c bar.c   # Source file list
    LOCAL_MODULE:= libfoo           # The name of shared library
    LOCAL_PRELINK_MODULE := false   # Prevent from prelink error
    
    include $(BUILD_SHARED_LIBRARY) # Start to build shared library
    • Static Library Template
    LOCAL_PATH:= $(call my-dir)     # call function my-dir will return the path of Android.mk
    include $(CLEAR_VARS)           # clean all variables mainly started with LOCAL_
    
    LOCAL_SRC_FILES:= $(call all-subdir-c-files)   # Source file list
    LOCAL_MODULE:= libbar           # The name of static library
    LOCAL_PRELINK_MODULE := false   # Prevent from prelink error
    
    include $(BUILD_STATIC_LIBRARY) # Start to build static library
    • If you have a tool that generates a source file from an input file using a user specified tool
    SRC := $(call my-dir)/include/vnd_generic.txt
    GEN := $(intermediates)/vnd_buildcfg.h
    TOOL := $(TOP_DIR)external/bluetooth/bluedroid/tools/gen-buildcfg.sh
    
    $(GEN): PRIVATE_PATH := $(call my-dir)
    $(GEN): PRIVATE_CUSTOM_TOOL = $(TOOL) $< $@
    $(GEN): $(SRC)  $(TOOL)
        $(transform-generated-source)
    
    LOCAL_GENERATED_SOURCES += $(GEN)
    • Adding a prebuilt library
       include $(CLEAR_VARS)
       LOCAL_MODULE := foo-prebuilt
       LOCAL_SRC_FILES := libfoo.so
       LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
       include $(PREBUILT_SHARED_LIBRARY)

    The LOCAL_EXPORT_C_INCLUDES definition here ensures that any module that
    depends on the prebuilt one will have its LOCAL_C_INCLUDES automatically
    prepended with the path to the prebuilt’s include directory, and will thus
    be able to find headers inside that.

    What is the LOCAL_MODULE_TAGS variable ?

    we can add LOCAL_MODULE_TAGS variable to Android.mk file to determine that module to be installed in that source code built. Here are the some defined tags and their meanings

    • eng

    – Default variant
    – Installs modules tagged with: eng, debug, user, and/or development
    – Installs non-apk modules that have no tags specified.
    – Installs APKs according to the product definition files.
    – adb is enabled by default.

    • user

    – Final release
    – Installs modules tagged with user
    – Installs non-apk modules that have no tags specified
    – Install APKs according to the product definition files
    – adb is disabled by default.

    • userdebug, Same as user except:

    – Also installs modules tagged with debug
    – adb is enabled by default

    How to include a shared library in your component ?

    LOCAL_SHARED_LIBRARIES := libfoo

    How to include a static library in your component ?

    LOCAL_STATIC_LIBRARIES
    These are the static libraries that you want to include in your module.
    Mostly, we use shared libraries, but there are a couple of places, like executables in sbin and host executables where we use static libraries instead.

    LOCAL_STATIC_LIBRARIES := libbar

    LOCAL_WHOLE_STATIC_LIBRARIES
    These are the static libraries that you want to include in your module without allowing the linker to remove dead code from them.
    This is mostly useful if you want to add a static library to a shared library and have the static library’s content exposed from the shared library.

    LOCAL_WHOLE_STATIC_LIBRARIES := libbar

    Include path list

    LOCAL_C_INCLUDES += \
                        usr/include           \
                        usr/local/include     \
                        $(LOCAL_PATH)/include

    Using c/cpp/cxx/ld flags

    LOCAL_CFLAGS   += -DONLY_C_NEEDED
    LOCAL_CXXFLAGS += -DONLY_CXX_NEEDED
    LOCAL_CPPFLAGS += -DBOTH_C_CXX_NEEDED
    LOCAL_LDFLAGS  += -Wl,--exclude-libs=libgcc_eh.a
    LOCAL_LDLIBS   += -lpthread

    Call subdir’s Android.mk

    Not recursively, just the directly sudir.

    include $(call all-subdir-makefiles)

    A full list of Android.mk variables

    These are the variables that you’ll commonly see in Android.mk files, listed alphabetically.

    But first, a note on variable naming:

    LOCAL_ – These variables are set per-module. They are cleared by the include $(CLEAR_VARS) line, so you can rely on them being empty after including that file. Most of the variables you’ll use in most modules are LOCAL_ variables.
    PRIVATE_ – These variables are make-target-specific variables. That means they’re only usable within the commands for that module. It also means that they’re unlikely to change behind your back from modules that are included after yours. Check the make documentation to find more about target-specific variables.
    INTERNAL_ – These variables are critical to functioning of the build system, so you shouldn’t create variables named like this, and you probably shouldn’t be messing with these variables in your makefiles.
    HOST_ and TARGET_ – These contain the directories and definitions that are specific to either the host or the target builds. Do not set variables that start with HOST_ or TARGET_ in your makefiles.
    BUILD_ and CLEAR_VARS – These contain the names of well-defined template makefiles to include. Some examples are CLEAR_VARS and BUILD_HOST_PACKAGE.
    Any other name is fair-game for you to use in your Android.mk. However, remember that this is a non-recursive build system, so it is possible that your variable will be changed by another Android.mk included later, and be different when the commands for your rule / module are executed.

    1 – NDK-provided variables:

    These GNU Make variables are defined by the build system before

    your Android.mk file is parsed. Note that under certain circumstances
    the NDK might parse your Android.mk several times, each with different
    definition for some of these variables.

    CLEAR_VARS
    Points to a build script that undefines nearly all LOCAL_XXX variables
    listed in the “Module-description” section below. You must include
    the script before starting a new module, e.g.:

    include $(CLEAR_VARS)

    BUILD_SHARED_LIBRARY
    Points to a build script that collects all the information about the
    module you provided in LOCAL_XXX variables and determines how to build
    a target shared library from the sources you listed. Note that you
    must have LOCAL_MODULE and LOCAL_SRC_FILES defined, at a minimum before
    including this file. Example usage:

    include $(BUILD_SHARED_LIBRARY) #Note that this will generate a file named lib$(LOCAL_MODULE).so

    BUILD_STATIC_LIBRARY
    A variant of BUILD_SHARED_LIBRARY that is used to build a target static
    library instead. Static libraries are not copied into your
    project/packages but can be used to build shared libraries (see
    LOCAL_STATIC_LIBRARIES and LOCAL_WHOLE_STATIC_LIBRARIES described below).
    Example usage:

    include $(BUILD_STATIC_LIBRARY) #Note that this will generate a file named lib$(LOCAL_MODULE).a

    PREBUILT_SHARED_LIBRARY
    Points to a build script used to specify a prebuilt shared library.
    Unlike BUILD_SHARED_LIBRARY and BUILD_STATIC_LIBRARY, the value
    of LOCAL_SRC_FILES must be a single path to a prebuilt shared
    library (e.g. foo/libfoo.so), instead of a source file.
    You can reference the prebuilt library in another module using
    the LOCAL_PREBUILTS variable (see docs/PREBUILTS.html for more information).

    PREBUILT_STATIC_LIBRARY
    This is the same as PREBUILT_SHARED_LIBRARY, but for a static library
    file instead. See docs/PREBUILTS.html for more.

    TARGET_ARCH
    Name of the target CPU architecture as it is specified by the
    full Android open-source build. This is ‘arm’ for any ARM-compatible
    build, independent of the CPU architecture revision.

    TARGET_PLATFORM
    Name of the target Android platform when this Android.mk is parsed.
    For example, ‘android-3’ correspond to Android 1.5 system images. For
    a complete list of platform names and corresponding Android system
    images, read docs/STABLE-APIS.html.

    refer to /build/core/envsetup.mk for more TARGET_ variables

    2 – NDK-provided function macros:

    The following are GNU Make ‘function’ macros, and must be evaluated
    by using ‘$(call <function>)’. They return textual information.

    my-dir
    Returns the path of the last included Makefile, which typically is
    the current Android.mk’s directory. This is useful to define
    LOCAL_PATH at the start of your Android.mk as with:

            LOCAL_PATH := $(call my-dir)

    IMPORTANT NOTE: Due to the way GNU Make works, this really returns
    the path of the last included Makefile during the parsing of
    build scripts. Do not call my-dir after including another file. For example, consider the following example:

            LOCAL_PATH := $(call my-dir)
    
            ... declare one module
    
            include $(LOCAL_PATH)/foo/Android.mk
    
            LOCAL_PATH := $(call my-dir)
    
            ... declare another module

    The problem here is that the second call to ‘my-dir’ will define
    LOCAL_PATH to $PATH/foo instead of $PATH, due to the include that
    was performed before that. For this reason, it’s better to put additional includes after
    everything else in an Android.mk, as in:

            LOCAL_PATH := $(call my-dir)
    
            ... declare one module
    
            LOCAL_PATH := $(call my-dir)
    
            ... declare another module
    
            # extra includes at the end of the Android.mk
            include $(LOCAL_PATH)/foo/Android.mk

    If this is not convenient, save the value of the first my-dir call
    into another variable, for example:

            MY_LOCAL_PATH := $(call my-dir)
    
            LOCAL_PATH := $(MY_LOCAL_PATH)
    
            ... declare one module
    
            include $(LOCAL_PATH)/foo/Android.mk
    
            LOCAL_PATH := $(MY_LOCAL_PATH)
    
            ... declare another module

    all-subdir-makefiles
    Returns a list of Android.mk located in all sub-directories of
    the current ‘my-dir’ path. For example, consider the following
    hierarchy:

            sources/foo/Android.mk
            sources/foo/lib1/Android.mk
            sources/foo/lib2/Android.mk

    If sources/foo/Android.mk contains the single line:

            include $(call all-subdir-makefiles)

    Then it will include automatically sources/foo/lib1/Android.mk and
    sources/foo/lib2/Android.mk This function can be used to provide deep-nested source directory
    hierarchies to the build system. Note that by default, the NDK
    will only look for files in sources/*/Android.mk

    this-makefile
    Returns the path of the current Makefile (i.e. where the function
    is called).

    parent-makefile
    Returns the path of the parent Makefile in the inclusion tree,
    i.e. the path of the Makefile that included the current one.

    grand-parent-makefile
    Guess what…

    import-module
    A function that allows you to find and include the Android.mk
    of another module by name. A typical example is:

          $(call import-module,<name>)

    And this will look for the module tagged <name> in the list of
    directories referenced by your NDK_MODULE_PATH environment
    variable, and include its Android.mk automatically for you. Read docs/IMPORT-MODULE.html for more details.

    3 – Module-description variables

    The following variables are used to describe your module to the build

    system. You should define some of them between an ‘include $(CLEAR_VARS)’
    and an ‘include $(BUILD_XXXXX)’. As written previously, $(CLEAR_VARS) is
    a script that will undefine/clear all of these variables, unless explicitly
    noted in their description.

    LOCAL_ASSET_FILES

    In Android.mk files that include $(BUILD_PACKAGE) set this to the set of files you want built into your app. Usually:
    
    LOCAL_ASSET_FILES += $(call find-subdir-assets)
    
    This will probably change when we switch to ant for the apps' build system.

    LOCAL_CC

    If you want to use a different C compiler for this module, set LOCAL_CC to the path to the compiler.
    If LOCAL_CC is blank, the appropriate default compiler is used.

    LOCAL_CXX

    If you want to use a different C++ compiler for this module, set LOCAL_CXX to the path to the compiler.
     If LOCAL_CXX is blank, the appropriate default compiler is used.

    LOCAL_CFLAGS

    If you have additional flags to pass into the C or C++ compiler, add them here. For example:
    
    LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1

    LOCAL_CPPFLAGS

    If you have additional flags to pass into only the C++ compiler, add them here. For example:
    
    LOCAL_CPPFLAGS += -ffriend-injection
    
    LOCAL_CPPFLAGS is guaranteed to be after LOCAL_CFLAGS on the compile line, so you can use it to override flags listed in LOCAL_CFLAGS.

    LOCAL_CPP_EXTENSION

    If your C++ files end in something other than ".cpp", you can specify the custom extension here. For example:
    
    LOCAL_CPP_EXTENSION := .cc
    
    Note that all C++ files for a given module must have the same extension; it is not currently possible to mix different extensions.

    LOCAL_NO_DEFAULT_COMPILER_FLAGS

    Normally, the compile line for C and C++ files includes global include paths and global cflags. 
    If LOCAL_NO_DEFAULT_COMPILER_FLAGS is non-empty,
     none of the default includes or flags will be used when compiling C and C++ files in this module.
     LOCAL_C_INCLUDES, LOCAL_CFLAGS, and LOCAL_CPPFLAGS will still be used in this case,
     as will any DEBUG_CFLAGS that are defined for the module.

    LOCAL_C_INCLUDES

    Additional directories to instruct the C/C++ compilers to look for header files in. 
    These paths are rooted at the top of the tree.
     Use LOCAL_PATH if you have subdirectories of your own that you want in the include paths. For example:
    
    LOCAL_C_INCLUDES += extlibs/zlib-1.2.3
    LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
    
    You should not add subdirectories of include to LOCAL_C_INCLUDES,
     instead you should reference those files in the #include statement with their subdirectories. 
    For example:
    
    #include <utils/KeyedVector.h>
    not #include <KeyedVector.h>
    
    There are some components that are doing this wrong, and should be cleaned up.

    LOCAL_MODULE_TAGS

    Set LOCAL_MODULE_TAGS to any number of whitespace-separated tags. 
    If the tag list is empty or contains droid, the module will get installed as part of a make droid. 
    Modules with the tag shell_$(TARGET_SHELL) will also be installed. 
    Otherwise, it will only get installed by running make <your-module> or with the make all pseudotarget.

    LOCAL_REQUIRED_MODULES

    Set LOCAL_REQUIRED_MODULES to any number of whitespace-separated module names, like "libblah" or "Email".
     If this module is installed, all of the modules that it requires will be installed as well. 
    This can be used to, e.g., ensure that necessary shared libraries or providers are installed when a given app is installed.

    LOCAL_FORCE_STATIC_EXECUTABLE

    If your executable should be linked statically, set LOCAL_FORCE_STATIC_EXECUTABLE:=true. 
    There is a very short list of libraries that we have in static form (currently only libc).
     This is really only used for executables in /sbin on the root filesystem.

    LOCAL_GENERATED_SOURCES

    Files that you add to LOCAL_GENERATED_SOURCES will be automatically generated and then linked in when your module is built.
     See the Custom Tools template makefile for an example.

    LOCAL_JAVACFLAGS

    If you have additional flags to pass into the javac compiler, add them here. For example:
    
    LOCAL_JAVACFLAGS += -Xlint:deprecation

    LOCAL_JAVA_LIBRARIES

    When linking Java apps and libraries, LOCAL_JAVA_LIBRARIES specifies which sets of java classes to include.
     Currently there are two of these: core and framework. In most cases, it will look like this:
    
    LOCAL_JAVA_LIBRARIES := core framework
    
    Note that setting LOCAL_JAVA_LIBRARIES is not necessary (and is not allowed) when building an APK with "include $(BUILD_PACKAGE)".
     The appropriate libraries will be included automatically.

    LOCAL_LDFLAGS

    You can pass additional flags to the linker by setting LOCAL_LDFLAGS. 
    Keep in mind that the order of parameters is very important to ld, so test whatever you do on all platforms.

    LOCAL_LDLIBS

    LOCAL_LDLIBS allows you to specify additional libraries that are not part of the build for your executable or library.
     Specify the libraries you want in -lxxx format; they're passed directly to the link line.
     However, keep in mind that there will be no dependency generated for these libraries. 
    It's most useful in simulator builds where you want to use a library preinstalled on the host. 
    The linker (ld) is a particularly fussy beast, so it's sometimes necessary to pass other flags here if you're doing something sneaky. Some examples:
    
    LOCAL_LDLIBS += -lcurses -lpthread
    LOCAL_LDLIBS += -Wl,-z,origin

    LOCAL_NO_MANIFEST

    If your package doesn't have a manifest (AndroidManifest.xml), then set LOCAL_NO_MANIFEST:=true. 
    The common resources package does this.

    LOCAL_PACKAGE_NAME

    LOCAL_PACKAGE_NAME is the name of an app. For example, Dialer, Contacts, etc. 
    This will probably change or go away when we switch to an ant-based build system for the apps.

    LOCAL_PATH

    The directory your Android.mk file is in. You can set it by putting the following as the first line in your Android.mk:
    
    LOCAL_PATH := $(my-dir)
    
    The my-dir macro uses the MAKEFILE_LIST variable, so you must call it before you include any other makefiles.
     Also, consider that any subdirectories you inlcude might reset LOCAL_PATH, so do your own stuff before you include them.
     This also means that if you try to write several include lines that reference LOCAL_PATH, it won't work,
     because those included makefiles might reset LOCAL_PATH.

    LOCAL_POST_PROCESS_COMMAND

    For host executables, you can specify a command to run on the module after it's been linked.
     You might have to go through some contortions to get variables right because of early or late variable evaluation:
    
    module := $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)
    LOCAL_POST_PROCESS_COMMAND := /Developer/Tools/Rez -d __DARWIN__ -t APPL\
           -d __WXMAC__ -o $(module) Carbon.r

    LOCAL_PREBUILT_EXECUTABLES

    When including $(BUILD_PREBUILT) or $(BUILD_HOST_PREBUILT), set these to executables that you want copied.
     They're located automatically into the right bin directory.

    LOCAL_PREBUILT_LIBS

    When including $(BUILD_PREBUILT) or $(BUILD_HOST_PREBUILT), set these to libraries that you want copied.
     They're located automatically into the right lib directory.

    LOCAL_SHARED_LIBRARIES

    These are the libraries you directly link against. You don't need to pass transitively included libraries.
     Specify the name without the suffix:
    
    LOCAL_SHARED_LIBRARIES := \
        libutils \
        libui \
        libaudio \
        libexpat \
        libsgl

    LOCAL_SRC_FILES

    The build system looks at LOCAL_SRC_FILES to know what source files to compile -- .cpp .c .y .l .java. For lex and yacc files,
     it knows how to correctly do the intermediate .h and .c/.cpp files automatically. 
    If the files are in a subdirectory of the one containing the Android.mk, prefix them with the directory name:
    
    LOCAL_SRC_FILES := \
        file1.cpp \
        dir/file2.cpp

    LOCAL_STATIC_LIBRARIES

    These are the static libraries that you want to include in your module. 
    Mostly, we use shared libraries, but there are a couple of places, 
    like executables in sbin and host executables where we use static libraries instead.
    
    LOCAL_STATIC_LIBRARIES := \
        libutils \
        libtinyxml

    LOCAL_MODULE

    LOCAL_MODULE is the name of what's supposed to be generated from your Android.mk. 
    For exmample, for libkjs, the LOCAL_MODULE is "libkjs" (the build system adds the appropriate suffix -- .so .dylib .dll). 
    For app modules, use LOCAL_PACKAGE_NAME instead of LOCAL_MODULE.

    LOCAL_MODULE_PATH

    Instructs the build system to put the module somewhere other than what's normal for its type. 
    If you override this, make sure you also set LOCAL_UNSTRIPPED_PATH if it's an executable or a shared library 
    so the unstripped binary has somewhere to go. An error will occur if you forget to.

    LOCAL_UNSTRIPPED_PATH

    Instructs the build system to put the unstripped version of the module somewhere other than what's normal for its type.
     Usually, you override this because you overrode LOCAL_MODULE_PATH for an executable or a shared library.
     If you overrode LOCAL_MODULE_PATH, but not LOCAL_UNSTRIPPED_PATH, an error will occur.

    LOCAL_WHOLE_STATIC_LIBRARIES

    These are the static libraries that you want to include in your module without allowing the linker to remove dead code from them. 
    This is mostly useful if you want to add a static library to a shared library and have the static library's content exposed from the shared library.
    
    LOCAL_WHOLE_STATIC_LIBRARIES := \
        libsqlite3_android

    LOCAL_YACCFLAGS

    Any flags to pass to invocations of yacc for your module.
     A known limitation here is that the flags will be the same for all invocations of YACC for your module.
     This can be fixed. If you ever need it to be, just ask.
    
    LOCAL_YACCFLAGS := -p kjsyy

    references

    https://sites.google.com/site/fourdollars/android/android-mk

    http://elinux.org/Android_Build_System

    aosp/build/core/build-system.html
    aosp/ndk/docs/ANDROID-MK.html
    aosp/ndk/docs/PREBUILTS.html