I have glibc compiled for arm which is different from Android glibc or the bionic C as the glibc environment I have complied will help in providing more api's.
Now I can copy the glibc environment on /system/ folder while Android is running, and on doing chroot I can run my programs on glibc environment.
Currently I am compiling glibc and Android separately and then tarring the glibc and copying it on Android emulator sdcard and then untarring it on /system folder and then doing chroot on /system/glibc
I compile glibc separately and then place it somewhere in Android source code.
Now while compiling Android source, what should I do so that the entire prebuilt folder structure of glibc gets copied to /system folder and become part of part of system.img.
With this when I copy the system.img to Android emulator and launch it, glibc is already present in /system folder and just need to run the apps in glibc environment.
UPDATE
after I did as per Yuri mentioned in his answer (I created glibc folder and copied everything into it), when I compile the code I get below output.
build/core/main.mk:490: * Some files have been added to ALL_PREBUILT.
build/core/main.mk:491: *
build/core/main.mk:492: * ALL_PREBUILT is a deprecated mechanism that
build/core/main.mk:493: * should not be used for new files.
build/core/main.mk:494: * As an alternative, use PRODUCT_COPY_FILES in
build/core/main.mk:495: * the appropriate product definition.
build/core/main.mk:496: * build/target/product/core.mk is the product
build/core/main.mk:497: * definition used in all products.
build/core/main.mk:498: *
build/core/main.mk:499: * unexpected glibc in ALL_PREBUILT
build/core/main.mk:500: *
build/core/main.mk:501: * ALL_PREBUILT contains unexpected files. Stop.
So I added glibc in build/core/legacy_prebuilts.mk
But then I get
make: * No rule to make target mkdir', needed byout/target/product/generic/root/glibc'. Stop.
Finally I did it in a very unusual way.
I had 3 options:
Use BUILD_PREBUILT variable, but drawback it you can do it for a
single file, but I had multiple files and in a particular forlder
structure
Use PRODUCT_COPY_FILES. But somehow it was not working for me
PRODUCT_COPY_FILES is for a device, and it was not a new device for
me. I was working on emulator.
Using the solution given by Yuri, using ALL_PREBUILT +=, but as Yuri
mentioned it was for GB and I am using JB and ICS and hence was not
working for me.
The approach i took is to use shell script within the Android.mk file.
I used some like this:
Assume you have a folder named my_folder containing entire prebuilt folder structure which needs to be copied to anddroid out folder as is, inside my_folder, I created Android.mk and entered below text:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
$(shell mkdir -p $(TARGET_OUT)/my_folder/)
$(shell cp -rf $(LOCAL_PATH)/* `pwd`/$(TARGET_OUT)/my_folder/)
This way all my prebuilt set of files and folders in my_folder directory were copied as is to system folder in android out.
I hope this helps someone.
PRODUCT_COPY_FILES must be placed in product mk files (device/mydevice/..), not module files (Android.mk). This is mentioned here.
This format is used for copying dirs:
PRODUCT_COPY_FILES += $(call find-copy-subdir-files,*,vendor/mydir,system/app)
This command is not working for apk files though, giving error:
build/core/Makefile: *** Prebuilt apk found in PRODUCT_COPY_FILES: vendor/mydir/ray-system-ui-release.apk:system/app/ui-release.apk, use BUILD_PREBUILT instead!. Stop.
Here is an example from the book "Embedded Android" that will help you. Create a folder in the root of your aosp project called rootfs-glibc, put there the code that you want to copy, and create there Android.mk file with the following content:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
# This part is a hack, we're doing "addprefix" because if we don't,
# this dependency will be stripped out by the build system
GLIBC_ROOTFS := $(addprefix $(TARGET_ROOT_OUT)/, rootfs-glibc)
$(GLIBC_ROOTFS): mkdir -p $(TARGET_ROOT_OUT) cp -af $(TOPDIR)rootfs-glibc/* $(TARGET_ROOT_OUT) rm
# The last command just gets rid of this very .mk since it's copied as-is
ALL_PREBUILT += $(GLIBC_ROOTFS)
There is a note that this is true for Gingerbread. Maybe in newer versions of Android the make system has been changed.
Consider using a PHONY_PACKAGE with a custom installation step.
Unlike the $(shell cp whatever) answer above, this will only run during the installation step, rather than on every Make step (which is certainly not what you want).
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := some_module
LOCAL_ADDITIONAL_DEPENDENCIES := FORCE # Decide if you need this
LOCAL_POST_INSTALL_CMD = cd $(LOCAL_PATH) && cp -a mystuff $(TARGET_OUT_WHATEVER)
include $(BUILD_PHONY_PACKAGE)
I was thinking if I could do this way
1. I have both android and glibc compiled separetely.
2. Once both are compiled, I manually copy the glibc entire folder to /out/target/product/generic/system/glibc/ folder
3. Then I run "make snod"
Would that work?
Related
I have multiple static libs that are built using jni. I have a scheme that includes other mk files, etc to allow me to share compile settings, include files from other dependent projects, etc.
I have set it up successfully on the mac and have been building it. However, when I tried to do the same in windows under cygwin I'm running into issues...
Here is my jni/Android.mk file..
LOCAL_PATH := $(call my-dir)
INJ_PROJECT_PATH := $(PWD)
include $(INJ_PROJECT_PATH)/jni/Project.mk
The problem I'm seeing is that ndk-build is complaining about the Project.mk file. Here is what I'm seeing..
shammi#SHAMMIDEV /cygdrive/c/projects/injitiProjects/injitiEngine/Engine/Core
$ ndk-build.cmd NDK_APP_OUT=../../build/Android/Engine/release
jni/Android.mk:5: /cygdrive/c/projects/injitiProjects/injitiEngine/Engine/Core/jni/Project.mk: No such file or directory
jni/Android.mk:5: /cygdrive/c/projects/injitiProjects/injitiEngine/Engine/Core/jni/Project.mk: No such file or directory
jni/Android.mk:5: /cygdrive/c/projects/injitiProjects/injitiEngine/Engine/Core/jni/Project.mk: No such file or directory
jni/Android.mk:5: /cygdrive/c/projects/injitiProjects/injitiEngine/Engine/Core/jni/Project.mk: No such file or directory
C:/projects/Android/sdk/ndk-bundle/build//../build/core/build-all.mk:89: Android NDK: WARNING: There are no modules to build in this project!
make: *** No rule to make target `/cygdrive/c/projects/injitiProjects/injitiEngine/Engine/Core/jni/Project.mk'. Stop.
I have confirmed that /cygdrive/c/projects/injitiProjects/injitiEngine/Engine/Core/jni/Project.mk does exist, and I am the owner and it has read permissions for user/group/other.
Again, this exact same setup works absolutely fine on the mac. I'm just looking at having a portable dev environment.
What am I missing here..?
I guess I forgot that ndk-build.cmd was a windows shell batch script (DOH).
The answer was that I was able to call /build/ndk-build which is a sh script that is comfortable running in cygwin.
You probably need to use LOCAL_PATH instead of PWD. I'm not really sure how PWD gets set (I think it's a make builtin?), but we actually have control over LOCAL_PATH and can make sure it gets set in the right way for cygwin.
Instead of include what if you define it to be APP_BUILD_SCRIPT?
for ex.
APP_BUILD_SCRIPT := jni/Android.mk
Also Id try $(shell $pwd) instead of $(PWD) if the above doesn't work, usually ndk doesn't interpret shell commands for me if I don't use the shell in the parenthesis.
I've spent a day on this and can't seem to configure my dev environment for a NDK toolchain that will support standard C++ libraries. The story is I'm trying to cross compile libnfnetlink and libnetfilter_queue for ARM (Android).
First I'm using the following:
Nexus 5 with CyanogenMod 11 (I forget, doesn't matter I'm not even on the device yet)
Ubuntu 12.04 32-bit
Android SDK bundle: adt-bundle-linux-x86-20140702
Android NDK: android-ndk-r10c
There is a great blog on doing this here but its incomplete as Netfilter uses stlc++ and there's no word on a NDK install/setup that would work with simply calling ndk-build. Just copying the files into /jni and calling ndk-build won't work alone.
Anyways, my specific problem is when I straight copy the Netfilter lib source structure into an empty Project's /jni directory, I get this:
user#ubuntu:~/Projects/NetfilterTest/NetfilterNativeTest/jni$ ndk-build
[armeabi] Compile thumb : netfilter_queue <= libnetfilter_queue.c
In file included from /home/user/Projects/NetfilterTest/NetfilterNativeTest/jni/libnetfilter_queue/src/libnetfilter_queue.c:35:0:
/home/user/Projects/NetfilterTest/NetfilterNativeTest/jni/libnetfilter_queue/src/internal.h:4:20: fatal error: config.h: No such file or directory
compilation terminated.
make: *** [/home/user/Projects/NetfilterTest/NetfilterNativeTest/obj/local/armeabi/objs/netfilter_queue/libnetfilter_queue/src/libnetfilter_queue.o] Error 1
The config.h file can't be found. After some googling I realize its because the standard C++ libraries aren't available in the prebuilt tool chains.
Everything points to me creating my own tool chain. So I build my own cross compiler using the scripts that the NDK includes.
cd /home/user/android-ndk-r10c/build/tools
./make-standalone-toolchain.sh --platform=android-19 --ndk-dir=/home/user/android-ndk-r10c/ --install-dir=/home/user/android-ndk-r10c/prebuilt/android-arm/android-19
To confirm that config.h is included in my tool chain I searched for it. It's there:
user#ubuntu:~/Projects/NetfilterTest/NetfilterNativeTest/jni$ find /home/user/android-ndk-r10c/prebuilt/android-arm/android-19/ -iname config.h
/home/user/android-ndk-r10c/prebuilt/android-arm/android-19/sysroot/usr/include/linux/config.h
Naturally I need to setup my environment and the Android.mk
JAVA_HOME=/usr/local/java/jdk1.6.0_45
JRE_HOME=$JAVA_HOME/jre
ANDROID_SDK=/home/user/adt-bundle-linux-x86-20140702
ANDROID_NDK=/home/user/android-ndk-r10c
ANDROID_CHAIN=/home/user/android-ndk-r10c/prebuilt/android-arm/android-19
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin:$ANDROID_SDK/sdk/platform-tools:$ANDROID_SDK/sdk/tools:$ANDROID_NDK:$ANDROID_CHAIN/bin
SYSROOT=$ANDROID_NDK/platforms/android-19/arch-arm
CC=arm-linux-androideabi-gcc
export CC
export ANDROID_SDK
export ANDROID_NDK
export SYSROOT
export JAVA_HOME
export JRE_HOME
export PATH
Here's my Android.mk (based on Roman10's blog:
LOCAL_PATH:=$(call my-dir)
#####################################################################
# build libnflink #
#####################################################################
include $(CLEAR_VARS)
LOCAL_MODULE:=nflink
LOCAL_C_INCLUDES:= $(LOCAL_PATH)/libnfnetlink/include
LOCAL_SRC_FILES:=\
libnfnetlink/src/iftable.c \
libnfnetlink/src/rtnl.c \
libnfnetlink/src/libnfnetlink.c
include $(BUILD_STATIC_LIBRARY)
#####################################################################
# build libnetfilter_queue #
#####################################################################
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/libnfnetlink/include \
$(LOCAL_PATH)/libnetfilter_queue/include
LOCAL_MODULE:=netfilter_queue
LOCAL_SRC_FILES:=libnetfilter_queue/src/libnetfilter_queue.c
LOCAL_STATIC_LIBRARIES:=libnflink
include $(BUILD_STATIC_LIBRARY)
#####################################################################
# build our code #
#####################################################################
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/libnfnetlink/include \
$(LOCAL_PATH)/libnetfilter_queue/include
LOCAL_MODULE:=nfqnltest
#LOCAL_LDLIBS:=-lstdc++
LOCAL_SRC_FILES:=nfqnl_test.c
LOCAL_STATIC_LIBRARIES:=libnetfilter_queue
LOCAL_LDLIBS:=-llog -lm
include $(BUILD_EXECUTABLE)
I still get config.h not found using ndk-build.
I've read that the ndk-build command leverages a config.mk/setup.mk that Google includes in the NDK and has to be modified to point to an alternative toolchain.
I'm completely floored that Google's own tools can't simply point to a custom toolchain that they give you scripts to create. If anyone has any suggestions on how I can use my toolchain to compile Netfilter or just in general it would be a great help.
Thanks in advance!
I can't find any reference to either internal.h or config.h when I search for a version of libnetfilter_queue.c on the web, so I'm not sure what version of the file you're using - can you point to which one you have?
Also, the config.h it looks for isn't the one you found in your toolchain (which should be included as linux/config.h) but most probably is one that you're expected to generate by running a configure script. So unless you've run the configure script (or have a pregenerated config.h from elsewhere) you can't really build it.
Finally, nothing of this has anything to do with libstdc++ since all your source files seem to be pure C, not C++.
I need to add the timetest directory's executable to the system.img file so that I can access the command from the shell. The location is at : https://android.googlesource.com/platform/system/extras/+/android-4.4.4_r1/tests/timetest/. So what I did was to go into the timetest directory and issue the following command:
mm snod
The output was as follows:
PRODUCT_COPY_FILES device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml ignored.
make: Entering directory `/home/username/android_built/android'
target thumb C: timetest <= frameworks/base/cmds/timetest/timetest.c
target StaticExecutable: timetest (out/target/product/hammerhead/obj/EXECUTABLES/timetest_intermediates/LINKED/timetest)
target Symbolic: timetest (out/target/product/hammerhead/symbols/sbin/timetest)
target Strip: timetest (out/target/product/hammerhead/obj/EXECUTABLES/timetest_intermediates/timetest)
Install: out/target/product/hammerhead/root/sbin/timetest
make: Leaving directory `/home/username/android_built/android'
The file installation part has been left out for clarity.
The following output is after I tried copying the timetest into frameworks/base/cmds as detailed in this question : android AOSP, adding new executable [.c] code. I also tried it directly.
I then looked at the entire phone including the xbin,bin directories . I also used find / -name "timetest", but the executable is nowhere to be found. What am I doing wrong?
I'm not actually sure how you are installing timetest to your device, but if you are just adb pushing the result to your device then you will likely have a hard time running that.
If you look at the Android.mk file for timetest you will see that it is labeled as "optional"
LOCAL_MODULE_TAGS := optional
However after grepping through all the make files, there is no build variant which includes this in a build. If you have your own device make file you can add it there, but if you just want to make this work quickly you can add it to the list of PRODUCT_PACKAGES in the build/target/product/core_minimal.mk file. There will be a list that looks something like:
PRODUCT_PACKAGES += \
BackupRestoreConfirmation \
DownloadProvider \
HTMLViewer \
MediaProvider \
Just add timetest into that list. After that do a make installclean and rebuild your device and you should have timetest included in sbin.
I'm experimenting with a rooted Android tablet. I need to run some system applications in C/C++ that can run as native apps with/without using the NDK. This would work like existing command line applications such as toolbox as a native ARM Linux executable.
Is that a possibility?
Yes, you can. And you can do it using the NDK which you make things easier to you , cross-compiling to all platforms supported by Android (ARM variants and x86). You just need to do like you would do to create a shared library for native Java methods. Just make sure you change the makefile to use BUILD_EXECUTABLE instead of BUILD_SHARED_LIBRARY to create an executable. Of course you won't need the APK folder structure, just the "jni" folder.
Tutorial
Create the project folders:
mkdir project_folder
cd project_folder/jni
NDK_PROJECT_PATH=<path to>/project_folder
Create the Android.mk makefile in the jni folder
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := teste
LOCAL_SRC_FILES := teste.c
include $(BUILD_EXECUTABLE)
Create also your source code in the jni. In this case, you can see from above makefile, it is teste.c:
#include <stdio.h>
int main (){
puts("Hello World");
return 0;
}
Now go up to your project folder and run ndk-build from there:
# ~/Downloads/android-ndk-r8b/ndk-build
Compile thumb : teste <= teste.c
Executable : teste
Install : teste => libs/armeabi/teste
Although it is output to a lib folder it is a executable, as you can inspect with file
#file libs/armeabi/teste
libs/armeabi/teste: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
Yes, it's possible. When you download the NDK you get a set of tools (compiler, linker, etc.), headers and libraries. It's not significantly different from other cross compilation environments.
The NDK comes with a cross compiler and enough of a freestanding programming environment (includes and libs) to port simple C/C++ applications to run as native Android binaries. Check out the docs/STANDALONE-TOOLCHAIN.html file in the NDK for documentation. (It's available online at kandroid.com.)
I believe that the NDK does not have access to enough system services to write a complete app. You'll still have to write the scaffolding of the app in Java, but you can write plenty of native libraries for the Java to call.
I'm building an OpenGL based app - writing in native C/C++.
I want to have my native files in a single location and only linked to the project ( so when I edit them in XCode/Eclipse the other project already has the updated files ). However, I can't figure out how to get ndk-build to build files that aren't actually in the JNI folder. Symbolic links ( in OSX ) didn't do the trick.
I keep getting
make: *** No rule to make target `/Developer/SDKs/android-ndk-r7b/build/core/myfile.cpp', needed by `obj/local/armeabi/objs/glHelloArrow/myfile.o'. Stop.
Any ideas?
I build outside of JNI folder on Windows. My Android.mk includes a makefile in a different folder:
LOCAL_PATH := $(MY_WORKSPACE)/path/jni
include $(MY_WORKSPACE)/path/jni/Src.mk
where the actual sources are listed:
LOCAL_SRC_FILES := \
a.cpp \
b.cpp \
etc.
One caveat is - make does not work right with relative paths. Or rather, it does, but assumes the path to be relative to the current folder, which in case of the ndk-build process can be all over the place. Thus the env variable that denotes the root of the file location.
Some details here.
I have a similar issue with cross-platform codebase. I've not found any way to do this.
My workaround is to create a symlink from my source code root directory into jni, so I can give the NDK build system paths like jni/link/common/foo.c.
Just be sure that you remove the symlink if you ever need to run tools that do recursive directory traversals...