I don’t know how good Android Studio support for native apps is nowadays (it changes from week to week!). Up to a few months ago, Gradle, the build system used by AS, had poor support for native development. If you’re having problems, you may find it easier to workaround it completely when it comes to build and debug C/C++ applications.
To debug a native Android application, a binary called gdbserver and its associated gdb.setup must be included in the generated APK file. Including this into the APK can be very painful in Gradle, so here’s a workaround I found:
- Build your stuff the way you normally would (I’m assuming you know already how to build a native app, and if you don’t there are guides online that explain it much better than I could).
- Deploy your application the way you normally would.
- Discover ndk-gdb won’t run. Bang forehead against keyboard a few times.
- After losing some hours looking at logs, figure out there’s no gdbserver included in your apk.
- Lose some more hours trying to figure out how to include it in your apk using Gradle.
- Give up. Bang forehead against keyboard some more.
- find the gdbserver and gdb.setup in your build directory.
- adb push each of these files to the device.
- Using adb shell, move the files you copied to /data/app-lib/com.yourapp/ – you may need to root your device for this.
- Profit! ndk-gdb now works.
Edit: remember you may need to chmod +777 your gdbserver.
I always forget about two very useful make variables, so I’ll leave this here: $(COMPILE.cpp), $(LINK.cpp).
It’s easy, instead of writing a rule as
foo.o: foo.cpp g++ -c foo.coo
you should instead write this:
foo.o: foo.cpp $(COMPILE.cpp) foo.coo
COMPILE.cpp will have the default compiler you are supposed to use, and probably some helpful parameters as well. Likewise, LINK.cpp will have the linker you are supposed to use.
There are many useful predefined variables in make. Be sure to check them all by running “make -p” in a console.
If you’re changing your vimrc, it can get boring to close and restart it only to see the changes applied. Want something quicker? You can “:so %”. So stands for source, so you’ll just be telling vim “include this file”. % happens to be the path to the current file. If you’re not editing your .vimrc but for some reason you still want to reload it, just use “so ~/.vimrc” instead.
Crosscompiling is always fun. No matter how ready-to-use it’s packaged, and Android does a pretty decent job at that, you’re still bound to find problems that leak through the abstraction layers. If something says it’s dummy-proof, I always find the way to perfect myself and be even dumber. For people like me; do yourselves a favour and start launching ndk-gdb this way:
ndk-gdb --start --verbose
Using the –verbose parameter will probably reveal some hidden errors. For example, when I forgot to chmod 777 my gdbserver binary:
## COMMAND: adb_cmd pull /system/bin/app_process ./obj/local/armeabi-v7a/app_process run-as: exec failed for /data/data/com.nico.trippingsdcardphotomanager/lib/gdbserver Error:Permission denied 117 KB/s (9560 bytes in 0.079s) Pulled app_process from device/emulator.
I have been working in an awesome Android app recently, so I’d like to throw in a shameless self-plug here. Oh, wait, it’s my blog. It’s all basically a big shameless self-plug, isn’t it? Anyway, I’ve been working on https://github.com/nicolasbrailo/TrippingSdCardPhotoManager , an open source SD card photo manager for Android.
Why an SD card photo manager? Whenever I go on holidays I never have enough SD cards to store all the snaps I take. Luckily I’m a crappy photographer, so I end up deleting half of the pictures I took during a day. This makes it easy to somewhat re-use the same SD card. In my experience, Android is not always great when it comes to managing files from an external SD card mounted through an USB adapter, hence this little app was born: it’ll let you select the directory you want to use to manage pictures, from anywhere in the filesystem. It’s also somewhat faster than the native gallery app, which is a plus when working with a slow-ish SD card.
This app also supports some stuff I find useful in my workflow, like renaming the current directory to something more meaningful than “YourCamera4242”, backing stuff up in the device and batch deleting files. It also packs a version of ImageMagick I ported for Android, so in theory you can use your Android device to do anything you can do with a regular “mogrify” command in Linux.
The app is not available in Playstore, mostly because I’m a cheap bastard and don’t want to pay the 10 bucks Google charges you to create an account, only to publish an open source application.
You can still install the APK from this link: https://github.com/nicolasbrailo/TrippingSdCardPhotoManager/releases
– or you can contribute to the open source world (?) and buy me a Play Store account.
If your buggy program generates lots of child processes, gdb will keep attached to the parent program and let all the children run loose. If you’re having problems to find what causes your crash this is probably not what you want: for those occasions gdb has a very helpful flag called detach on fork.
With detach on fork you can tell gdb to keep debugging the parent, follow the children, or keep track of all processes. Must be nice to troubleshoot forkbombs with this option.
In C++, is there a difference between cerr and cout, other than using a different file descriptor? Turns out you can learn something new every day.
Whenever I just want to add a quick print statement because I’m too lazy to debug something, I used to use cout. All along I thought cout and cerr would be exactly the same for my use case, but turns out there’s a slight difference: cout is buffered, cerr is not. This very small difference can have a huge impact, because you shouldn’t need to flush cerr after a write to make sure the changes are visible, it should happen automagicaly. In turn cerr might be slightly slower, but you probably don’t care about that when writing cerr << “I’m here!”.
If you use vim daily, you probably have a bunch of maps for your most common tasks. You should also remember you can assign the same key to do different things according to which mode you are
in. For example, let’s say you have a mapping to open a new tab:
map <leader>t :tabnew<cr>
You can also map t to open a new tab using the selected text as a filename. You just need to define two mappings:
nmap <leader>t :tabnew<cr> vmap <leader>t :call Foo()<cr>
nmap stands for normal (mode) map, vmap for visual. How to get the text under the cursor is a bit more complex and out of scope for this vim tip, but you might want to check http://vim.wikia.com/wiki/Mapping_keys_in_Vim_-_Tutorial_%28Part_1%29.
Remember to check “:help map” for a list of all mode mappings.