Hello-Jni on Windows, Android NDK - build-local.mk: No such file - android

I have tried scouring the Internet and StackOverflow (too many articles to count) but cannot find assistance that is all of these things:
More recent than 2013
Does not require Cygwin if developing
on Windows
Is geared to Android Studio, NOT Eclipse.
I am diving head first into Android development for the very first time and the project I have newly joined depends on developing with the NDK. I've been reading the docs that come with the NDK but have run into a stone wall with this sample.
I am trying to build hello-jni, the sample project within the NDK. Here is my environment:
Android Studio 1.4 (most up to date, stable version currently available)
NDK version: r10e
OS: Windows 7
Contents of Application.mk file:
APP_ABI := all64 // Came with 'all', read somewhere on SO that it
// should be 'all64'. Result is the same.
Contents of Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
My PATH environment variable includes a path to my NDK root folder and to \prebuilt\windows-x86_64\bin (because I read on one of many articles that it should.) When I navigate to the hello-jni root folder though, and call ndk-build, I am only presented with errors.
c:\NDK\android-ndk-r10e\build\core\build-local.mk:40: c:/NDK/android-ndk-r10e/build/core/build/core/init.mk: No such file or directory
c:\NDK\android-ndk-r10e\build\core\build-local.mk:191: \add-application.mk: No such file or directory
c:\NDK\android-ndk-r10e\build\core\build-local.mk:206: \setup-imports.mk: No such file or directory
c:\NDK\android-ndk-r10e\build\core\build-local.mk:223: \build-all.mk: No such file or directory
make.exe: *** No rule to make target `\build-all.mk'. Stop.
If anything else is required for people to assist me, say the word I will provide what I can. All help will be greatly appreciated.
EDIT:
Most of the articles of I've seen for Windows mention Cygwin, but according to the docs, it isn't needed. If this is incorrect, please correct me?
Except from \android-ndk-r10e\docs\Programmers_Guide\html\md_3__key__topics__building__s_t_a_n_d_a_l_o_n_e-_t_o_o_l_c_h_a_i_n.html
Windows support
The Windows binaries do not depend on Cygwin. The good news is that they are thus faster, the bad news is that they do not understand the Cygwin path specification like /cygdrive/c/foo/bar (instead of C:/foo/bar).
The NDK build system ensures that all paths passed to the compiler from Cygwin are automatically translated, and deals with other horrors for you. If you have a custom build system, you may need to deal with the problem yourself.

I can't take the credit for this answer, a coworker kindly sleuthed it out for me. When he found the answer, I demanded to know what else he had done, because clearly I must have missed some magic? I only saw him switch two lines in a make file, there had to be more? Alas, no. This alone was the source of my woe.
While I'm hesitant to call it an error within the NDK because I don't know how it works with Cygwin, neither of us can understand how this has ever worked for anyone building in native Windows, as the line I will be referencing is recorded in the git repository as being added back in 2011 or 2010. ( https://android.googlesource.com/platform/ndk/+/master/build/core/build-local.mk )
To aid explanation, here is the first line of my error again:
c:\NDK\android-ndk-r10e\build\core\build-local.mk:40: c:/NDK/android-ndk-r10e/build/core/build/core/init.mk: No such file or directory
The first file that is unable to found is ...build/core/build/core/init.mk, which of course doesn't exist because build/core should not be repeated.
The command that begins the build, ndk-build.cmd, calls build\core\build-local.mk to begin the process. Inside this file the environment variable, NDK_ROOT, is recreated upon entry. Whatever my NDK_ROOT is, is irrelevant.
NDK_ROOT := $(dir $(lastword $(MAKEFILE_LIST)))
NDK_ROOT := $(strip $(NDK_ROOT:%build/core/=%))
NDK_ROOT := $(subst \,/,$(NDK_ROOT))
NDK_ROOT := $(NDK_ROOT:%/=%)
.
.
.
The second line strips the end of the current directory (the build/core/) from the end of my new NDK_ROOT, because the true root should be the parent directory of build and because it will be added back later to find all those 'missing' files. That's fine, except note the forward-slashes (/) used in the search. Windows does not use (or in my experience at least, usually does not return) forward-slashes, though it will often parse them if that is what it's given. (When changing directories, for example, I've found either to be acceptable as long as I already know where I need to go. Tab completion does not seem to function if my path ends with a /.)
Oh, but look at the third line (added way back in 2011)! A substitution is made of every backslash (\) in NDK_ROOT, replaced with forward-slash (/). So the replacement of build/core/ should go off without a hitch, right? Problem: it's too late.
The strip call has already occurred and if the NDK_ROOT received a path with backslashes instead of forward-slashes, build/core/ is never found and stripped from the variable. How did my coworker fix it? Easy. He switched the lines around:
NDK_ROOT := $(dir $(lastword $(MAKEFILE_LIST)))
NDK_ROOT := $(subst \,/,$(NDK_ROOT))
NDK_ROOT := $(strip $(NDK_ROOT:%build/core/=%))
NDK_ROOT := $(NDK_ROOT:%/=%)
My hello-jni project now builds, along with Teapot, another sample from the NDK, which I tried just to be sure. And so does native-audio, native-codec, native-media, and More Teapots. Haven't tried to run them yet... but I have no build errors.
I don't know if this fix will break Cygwin users, I don't have that on my box. I also don't know if it would break Linux environments because I don't have Linux on my box. But this may help native Windows users, and I hope so, because I uselessly beat my head on this for 3 or 4 days and read more SO articles than I ever care to at once.

Using a windows machine I encountered this error but it was saying the clear-vars.mk : No such file or directory. After I looked at the ndk-build.cmd in the directory
C:\Users\\AppData\Local\Android\Sdk\ndk-bundle\build
the file looks like this
#echo off
set NDK_ROOT=%~dp0\..
set PREBUILT_PATH=%NDK_ROOT%\prebuilt\windows-x86_64
if exist %PREBUILT_PATH% goto FOUND
set PREBUILT_PATH=%NDK_ROOT%\prebuilt\windows
:FOUND
"%PREBUILT_PATH%\bin\make.exe" -f "%NDK_ROOT%\build\core\build-local.mk" SHELL=cmd %*
But you will also find the same file name under directory
C:\Users\jmatthews\AppData\Local\Android\Sdk\ndk-bundle
and the file looks like this
#echo off
%~dp0\build\ndk-build.cmd %*
remove the second line so it looks like this with only 1 line echo off
#echo off
This file is called and messes up the Windows directory structure. After that I was able to compile on windows. Also I had issues with the project using a space in the directory so move your project location to directories without spaces.

Related

Native library not found on android build?

I am getting this error: unable to lookup library path for, native render plugin support disabled when I run my app on android. I think I am building the shared libraries incorrectly.
I am looking to build the source files from this repo. I'll say my build process and perhaps someone can spot a step I'm missing or doing incorrect.
Following this guide, I came up with this:
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libhydrogen
LOCAL_SRC_FILES := ..\hydrogen.c
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_PLATFORM := android-16
APP_OPTIM := release
APP_MODULES := libhydrogen
Next I:
Placed these files in the jni folder.
Called ndk-build.
Copied the .so files from the \libs folder and placed them in their respective folders in Unity (i.e. Hydrogen\Plugins\Android\arm64-v8a).
Made sure their platforms and CPU architectures were correct.
Built my app.
Here is the c# wrapper I am using.
Calling Hydrogen.Library.Initialize(); is then giving me this error.
Here is the full logcat related to this error.
And in the case my build process manages to be correct, and the .so files are fine; what else might cause this to happen?
Edit: I am trying to build for armeabi-v7a and `x86. Here are the .so file details, maybe there is something there that is not right? I am unfamiliar with c and since I haven't heard of anyone building this library for android, I wonder: could there be anything within the c source file that is incompatible with the NDK build process?
Native libraries are loaded by the native linker of the system, in your case, the linux dynamic linker: ld.so (it changes names sometimes, so I used that name, as you can check the man page in the documentation with that name).
For that to happen, in general, you need to provide a LD_LIBRARY_PATH environment variable to the java virtual machine, so it can effectively dlopen(3) it.
Think how different can be your development system to your target one.... and you'll easily get to that.
It was a bug with Unity! For some reason when switching the project's target platform some of my files would get corrupted. Strangely, it only seems to happen in this one project, but in any case the (temporary) solution is to re-import the plugin folder whenever I switch platforms.

ndk_build.cmd in cygwin not recognizing included mk files

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.

Android NDK code analysis not using defined variables

I think this problem started when upgrading to the Juno Eclipse. I believe the C/C++ build environment was probably upgraded as well at the same time. The NDK was not upgraded.
We have a large mass of C code that compiles under several platforms. We are using the crystax-ndk (r6) to compile our C++ code. To know when we are compiling for Android, we have defined the following in the Android.mk
LOCAL_CFLAGS := -DANDROID_NDK \
-DDISABLE_IMPORTGL \
...
Then in some files we will include different headers depending upon the platform
#ifdef ANDROID_NDK
...
Our code compiles just fine and seems to run fine. However, when opening certain files the C/C++ code analyzer will find many errors. This appears to be because the analyzer doesn't know about the ANDROID_NDK defined variable.
Any idea why the code analyzer is not using the same #defines as the compiler? The code is almost uneditable with all the bogus errors the analyzer is reporting.
I saw you're comment about the analyzer you were refering to.
Eclipse CDT (C/C++ Development Toolkit) does not support parsing Android.mk yet neither does the NDK plugin add that functionality at the time of writing this.
Possible (ugly/annoying) workaround: Set up a header file setting the defines you are missing and include that header file to all files.
Use LOCAL_CPPFLAGS for C++ files and LOCAL_CFLAGS for C files in your Android.mk

Compiling linked ( not copied ) files using NDK

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...

cannot find -lgnustl_static: Compiling Android SDL port with NDK r7

I'm trying to build this port of libSDL for Android, using the new Android NDK r7 release:
https://github.com/pelya/commandergenius
I know I am doing some things to some degree "unsupported": I am using cygwin&windows despite that being mentioned in the README as no longer being supported. That being said, I can hack out shell scripts and solve my problems as necessary and have it compiling but not linking.
So anyways I have compiling working until the linking (sorry for large block, relevant part trimmed below):
/cygdrive/c/and/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-ar crs obj/local/armeabi/libflac.a ./obj/local/armeabi/objs-debug/flac/src/ogg_decoder_aspect.o ./obj/local/armeabi/objs-debug/flac/src/md5.o ./obj/local/armeabi/objs-debug/flac/src/stream_decoder.o ./obj/local/armeabi/objs-debug/flac/src/fixed.o ./obj/local/armeabi/objs-debug/flac/src/memory.o ./obj/local/armeabi/objs-debug/flac/src/stream_encoder.o ./obj/local/armeabi/objs-debug/flac/src/window.o ./obj/local/armeabi/objs-debug/flac/src/cpu.o ./obj/local/armeabi/objs-debug/flac/src/ogg_encoder_aspect.o ./obj/local/armeabi/objs-debug/flac/src/lpc.o ./obj/local/armeabi/objs-debug/flac/src/float.o ./obj/local/armeabi/objs-debug/flac/src/bitmath.o ./obj/local/armeabi/objs-debug/flac/src/metadata_object.o ./obj/local/armeabi/objs-debug/flac/src/ogg_helper.o ./obj/local/armeabi/objs-debug/flac/src/metadata_iterators.o ./obj/local/armeabi/objs-debug/flac/src/bitreader.o ./obj/local/armeabi/objs-debug/flac/src/bitwriter.o ./obj/local/armeabi/objs-debug/flac/src/stream_encoder_framing.o ./obj/local/armeabi/objs-debug/flac/src/crc.o ./obj/local/armeabi/objs-debug/flac/src/format.o ./obj/local/armeabi/objs-debug/flac/src/ogg_mapping.o
C:/and/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld.exe: cannot find -lgnustl_static
collect2: ld returned 1 exit status
/cygdrive/c/and/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-ar crs obj/local/armeabi-v7a/libflac.a ./obj/local/armeabi-v7a/objs-debug/flac/src/ogg_decoder_aspect.o ./obj/local/armeabi-v7a/objs-debug/flac/src/md5.o ./obj/local/armeabi-v7a/objs-debug/flac/src/stream_decoder.o ./obj/local/armeabi-v7a/objs-debug/flac/src/fixed.o ./obj/local/armeabi-v7a/objs-debug/flac/src/memory.o ./obj/local/armeabi-v7a/objs-debug/flac/src/stream_encoder.o ./obj/local/armeabi-v7a/objs-debug/flac/src/window.o ./obj/local/armeabi-v7a/objs-debug/flac/src/cpu.o ./obj/local/armeabi-v7a/objs-debug/flac/src/ogg_encoder_aspect.o ./obj/local/armeabi-v7a/objs-debug/flac/src/lpc.o ./obj/local/armeabi-v7a/objs-debug/flac/src/float.o ./obj/local/armeabi-v7a/objs-debug/flac/src/bitmath.o ./obj/local/armeabi-v7a/objs-debug/flac/src/metadata_object.o ./obj/local/armeabi-v7a/objs-debug/flac/src/ogg_helper.o ./obj/local/armeabi-v7a/objs-debug/flac/src/metadata_iterators.o ./obj/local/armeabi-v7a/objs-debug/flac/src/bitreader.o ./obj/local/armeabi-v7a/objs-debug/flac/src/bitwriter.o ./obj/local/armeabi-v7a/objs-debug/flac/src/stream_encoder_framing.o ./obj/local/armeabi-v7a/objs-debug/flac/src/crc.o ./obj/local/armeabi-v7a/objs-debug/flac/src/format.o ./obj/local/armeabi-v7a/objs-debug/flac/src/ogg_mapping.o
C:/and/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld.exe: cannot find -lgnustl_static
collect2: ld returned 1 exit status
Relevant failure, if you can't parse that wall of text:
ld.exe: cannot find -lgnustl_static
Now, if I look at the Windows NDK release I find gnustl_* files here:
under ./android-ndk-r7/sources:
./cxx-stl/gnu-libstdc++/libs/armeabi/libgnustl_shared.so
./cxx-stl/gnu-libstdc++/libs/armeabi/libgnustl_static.a
./cxx-stl/gnu-libstdc++/libs/armeabi-v7a/libgnustl_shared.so
./cxx-stl/gnu-libstdc++/libs/armeabi-v7a/libgnustl_static.a
./cxx-stl/gnu-libstdc++/libs/x86/libgnustl_shared.so
./cxx-stl/gnu-libstdc++/libs/x86/libgnustl_static.a
I looked also at the linux android NDK distribution and they are packaged the same (only have libgnustl files, built, under the sources directory).
So I have 3 questions:
why would we be using -l to link libgnustl_static when it's a .a
file? Shouldn't that be just including the .a file in the object
list, or alternately be -lgnustl_shared?
why are these files only under "sources"? I would have expected them to be in the "toolchains" library NDK directory. How does anyone ever link against libgnustl?
Can I copy these files somewhere where they'll be seen by the linker? Just adding their directory with -L hasn't seemed to work, and plus I need to get the right versions linked with the right build target (armeabi vs armeabi-v7 vs x86)
This is a bug in gcc/NDK that manifests itself slightly different on Linux, Cygwin, and Windows (non Cygwin).
Here's what I did to fix it (works for Linux and for one of my developers who is blind and has to use Cygwin)...
Remove the line that says, APP_STL := gnustl_static from your Application.mk (it's broken in the NDK, and it's broken slightly differently on Linux Cygwin, Windows)
add a line to $(LOCAL_LDLIBS) in your Android.mk file that says:
$(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/libgnustl_static.a
also add two lines to Android.mk that say:
LOCAL_C_INCLUDES := $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.6/include
LOCAL_C_INCLUDES += $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include
The foregoing will accomplish what having, APP_STL := gnustl_static in your Application.mk was supposed to.
In case this plagues anyone else, the solution is to remove -lgnustl_static and instead list
c:\path\to\armeabi\libs\libgnustl_static.a in the linker command.
Do not use /cygdrive style path, as the linker will fail to find the file. Use actual c:\...

Categories

Resources