C, C++, Obj-C

常用语言,主要用于win32 OpenGL等GUI程序和2D/3D图形编程,也会包含一些如Objective-C等相关物.

Android Studio带C++项目提示More than one file was found with OS independent path问题修正

近日,在将一个旧Android Studio项目(带native c/c++)升级了新版本gradle 4.0.1后(Android Studio版本4.0.1),发现重新clean再构建时,提示:

More than one file was found with OS independent path ‘lib/armeabi-v7a/xxx.so’. If you are using jniLibs and CMake IMPORTED targets, see https://developer.android.com/studio/preview/features#automatic_packaging_of_prebuilt_dependencies_used_by_cmake

虽然一开始也是一脸茫然,但既然提示信息里都提供了连接了,那就看一下吧,顺带一提,给出的链接我写这篇博文的时候并不是最终信息位置,最终链接在这里:https://developer.android.com/studio/releases/gradle-plugin#cmake-imported-targets ,仔细阅读了一下,发现实际上是从gradle 4.0开始就对jni的预编译依赖引用方式做出了修改:

继续阅读…

解决Android NDK编译FFmpeg 4.2.2的x86 cpu版时的问题

老规矩,编译环境:Win10 1903,WSL ubuntu,ndk r20b,FFmpeg 4.2.2,首先分享下编译脚本:

#!/bin/bash
make clean

export NDK=/home/kres/android-ndk-r20b
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64/
API=21

function build_android
{
	echo "Compiling FFmpeg for $CPU"
	./configure \
		--prefix=$PREFIX \
		--enable-neon \
		--enable-hwaccels \
		--enable-gpl \
		--enable-postproc \
		--enable-shared \
		--enable-jni \
		--enable-mediacodec \
		--disable-decoders \
		    --enable-decoder=h264_mediacodec \
		    --enable-decoder=vp9 \
		    --enable-decoder=h264 \
		    --enable-decoder=mpeg4 \
		    --enable-decoder=aac \
		    --enable-decoder=aac_latm \
		    --enable-decoder=mjpeg \
		    --enable-decoder=png \
		    --enable-decoder=mpeg4_mediacodec \
		--disable-encoders \
		    --enable-encoder=vp9_vaapi --enable-encoder=h264_nvenc --enable-encoder=h264_v4l2m2m --enable-encoder=hevc_nvenc \
		--disable-demuxers \
		    --enable-demuxer=rtsp --enable-demuxer=rtp --enable-demuxer=flv --enable-demuxer=h264 \
		--disable-muxers \
		    --enable-muxer=rtsp --enable-muxer=rtp --enable-muxer=flv --enable-muxer=h264 \
		--disable-parsers \
		    --enable-parser=mpeg4video --enable-parser=aac --enable-parser=h264 --enable-parser=vp9 \
		--disable-protocols \
		    --enable-protocol=rtmp --enable-protocol=rtp --enable-protocol=tcp --enable-protocol=udp \
		--disable-bsfs \
		--disable-indevs --enable-indev=v4l2 \
		--disable-outdevs \
		--disable-filters \
		--disable-postproc \
		--disable-static \
		--disable-doc \
		--disable-ffmpeg \
		--disable-ffplay \
		--disable-ffprobe \
		--enable-avdevice \
		--disable-doc \
		--disable-symver \
		--cross-prefix=$CROSS_PREFIX \
		--target-os=android \
		--arch=$ARCH \
		--cpu=$CPU \
		--cc=$CC \
		--cxx=$CXX \
		--enable-cross-compile \
		--sysroot=$SYSROOT \
		--extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" \
		--extra-ldflags="$ADDI_LDFLAGS" \
		$ADDITIONAL_CONFIGURE_FLAG

		make clean
		make -j6
		make install
		echo "The Compilation of FFmpeg for $CPU is completed"

}
	#armv8-a
	ARCH=arm64
	CPU=armv8-a
	CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
	CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
	SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
	CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
	PREFIX=$(pwd)/android/$CPU
	OPTIMIZE_CFLAGS="-march=$CPU"
	build_android

	#armv7-a
	ARCH=arm
	CPU=armv7-a
	CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
	CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
	SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
	CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
	PREFIX=$(pwd)/android/$CPU
	OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
	build_android

	#x86
	ARCH=x86
	CPU=x86
	CC=$TOOLCHAIN/bin/i686-linux-android$API-clang
	CXX=$TOOLCHAIN/bin/i686-linux-android$API-clang++
	SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
	CROSS_PREFIX=$TOOLCHAIN/bin/i686-linux-android-
	PREFIX=$(pwd)/android/$CPU
	OPTIMIZE_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
	build_android

	#x86_64
	ARCH=x86_64
	CPU=x86-64
	CC=$TOOLCHAIN/bin/x86_64-linux-android$API-clang
	CXX=$TOOLCHAIN/bin/x86_64-linux-android$API-clang++
	SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
	CROSS_PREFIX=$TOOLCHAIN/bin/x86_64-linux-android-
	PREFIX=$(pwd)/android/$CPU
	OPTIMIZE_CFLAGS="-march=$CPU -msse4.2 -mpopcnt -m64 -mtune=intel"
	build_android

继续阅读…

由RapidJSON发现的成员函数与宏冲突问题

在使用RapidJson的时候,发现了一个之前很少注意到的问题:

F:\Projects\test\rapidjson-1.1.0\include\rapidjson\document.h(982,70): error : too few arguments provided to function-like macro invocation
if (a < static_cast(-std::numeric_limits::max())

乍一看好像不是很眼熟的错误提示,没看懂什么意思,惯例搜索引擎查,于是很快发现了这个: https://stackoverflow.com/questions/1394132/macro-and-member-function-conflict ,简单一看就反应过来了,原来是成员函数名(这里是max)和之前不知在哪定义过的同名max冲突了,编译器把本该作为成员函数调用的max当成作了替换,于是就出现了上面的错误。

继续阅读…

使用Android Studio 3.0+调试任意环境生成的APK中的Java和Native C/C++代码(APK调试debug)

自从Google抛弃Eclipse ADT转投IntelliJ IDEA搞出Android Studio后,Android的开发调试环境可以说是日臻完善,先是Android Studio 2.x加入了调试原生C/C++代码的功能,一解Android NDK开发调试不方便之困(想当年可是拜ndk开发调试所赐才熟练掌握了gdb命令行的各种操作…),现在的3.x又加入了直接调试任意apk中Java和native .so的功能:

测试了下,虽然过程中遇到了个小问题,不过最终还是成功了,基本能和AS开发的带C++ Support项目原生调试体验一致。下面记录下这个”小问题“的解决方法:
先说明下这个小问题是用AS调试任意apk中的.so时找不到调试符号,且无法定位到源码并命中断点的问题,也就是说是有源码调试!无源码调试理论上应该也可以,但不在本次研究范围之内。
继续阅读…

Android Studio通过CMake编译原生代码运行时符号(函数)丢失的问题

由于新版Android Studio的native调试功能实在是太好用了,所以试了下把旧版Cococs2d-x项目(大概是2.x版本吧)重建Android Studio项目。花了很长时间添加各种source,static library,prebuilt library以后,终于项目可以在Android Studio的cmake编译工具下成功编译链接并生成.so了,迫不及待的一运行,发现直接闪退,检查后发现是”Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnResume”这个cocos2d-x的jni函数没有找到!
初步检查了下,发现cmake编译出的cocos2d静态库.a中存在这个函数符号,但是最终生成的.so中确实是没有这个函数(使用ndk toolchain里面的nm),于是想到应该是链接时认为这个符号没有代码调用,被stripe掉了。
后来又仔细看了下Android.mk,发现玄机貌似在于

LOCAL_WHOLE_STATIC_LIBRARIES += cocos2dx_static

对cocos2dx的静态库使用了WHOLE的链接方式,于是开始查找同样功能在cmake中的实现方式,最后查的结果如下:
继续阅读…

quick-cocos2d-x-2.2.6的CCHTTPRequest在Android 5.0+系统上的崩溃问题

虽然是比较旧版本的quick了,但也许会有人需要此版本的项目重新编译运行在新版本Android系统上,或是有遇到类似问题可以供参考,所以此篇文章记录解决这个问题的方法。
报错的现象是在使用“network.createHTTPRequest”进行http访问的时候(也就是lua调用的CCHTTPRequest类),出现native crash,大致异常信息是“use of deleted local reference XXXX”,看下logcat中的调用栈信息可以发现是在CCHTTPRequest::setRequestMethodJava调用时导致的。
关于这个问题我以前曾经写过相关的文章:

[译]Android冰淇淋三明治ICS(4.0+)JNI局部引用的变化 – http://blog.k-res.net/archives/1525.html
Android NDK中多线程JNI的local reference释放问题 – http://blog.k-res.net/archives/1794.html

基本问题就是高版本安卓系统的JNI部分有一些关于Local Reference的改动,导致曾经没问题的JNI逻辑在新版本系统上crash,先放出修改吧,修改
lib\cocos2d-x\external\extra\platform\android\CCHTTPRequestAndroid.cpp这个文件中Android平台下对于CCHTTPRequest的实现,找到getClassID_,修改为如下所示:
继续阅读…

Android Studio中项目NDK原生部分整合方式

UPDATE 2016.11.14:
目前的新版Android Studio 2.2已经可以完美支持NDK原生代码整合,通过cmake以及lldb实现c/c++代码调试,并且支持代码补全等功能!

自从Android Studio出现以后,我就很少再使用Eclipse+ADT的组合做Android开发了,更快的反应速度和更人性化的操作方式以及智能感知方面等等的优势,确实体现出了Google最初宣传Android Studio时的大部分特点,不过这些种种优势目前还只是体现在Java应用开发部分,而对于需要用到C/C++的Android NDK开发时,目前还没有很好的支持,当然,参考目前Android Studio的版本迭代速度来看,这应该也只是时间问题,当初ADT刚出的时候也是问题多多,包括后来的CDT+NDK支持,最初也只是支持原生代码的编译生成so,过了很久很久的某次update才加入了原生代码的可视化调试功能(当时也是历尽万难才测试成功的,还只是很简单的混合ndk项目…)。

最近看到了ndk又更新到了r10b版本,而且又据说新版的Android Studio中已经加入了一些ndk支持,于是正好一次测试一下(Android Studio beta 0.8.14, android-ndk32-r10b-windows-x86_64):

继续阅读…

VS结合VisualGDB搭建OpenWrt交叉编译远程调试开发环境

由于此开发环境涉及3设备协同工作,因此先说明一下整体开发环境的配置以及每部分所负责的功能:
1.Windows PC
这里我用的是64位Win7,作为VS的安装环境Windows自然是必不可少的,本机主要用于结合VisualGDB插件完成项目创建,上传编译机编译并部署执行程序到测试机完成gdbserver远程调试(自然是背后gdb前脸VS的全图形可视化调试)
2.Linux PC
这个我这里是CentOS Linux release 7.2.1511 64bit,安装于VMWare虚拟机上(当然也可以用真机,效果更佳!),作为交叉编译OpenWrt执行程序的编译机,由VisualGDB通过ssh连接同步Win机上的项目源码,make文件等并进行编译,同时还作为gdb客户端连接OpenWrt调试服务端并由VisualGDB传递gdb调试操作间接实现Win端的VS图形化调试
3.OpenWrt Router
这个我这里使用的是联想的Y1S路由器,MT7620A mips架构,作为整个开发环境的目标平台,接收Linux编译后的执行程序,并负责启动gdbserver作为远程调试的服务端

整体环境介绍完了,首先要做的是搭建起Linux机上的OpenWrt命令行开发环境(Y1S对应的是OpenWrt-SDK-ramips-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2),并且保证可以使用原始gdb的方式成功进行命令行模式的远程调试,这个就不赘述了,网上有很多相关教程。补充一点,在gdb调试过程中可能会遇到(OpenWrt上线./gdbserver :9876 /mnt/sda1/kcamd启动调试进程):

./scripts/remote-gdb 192.168.99.1:9876 ./build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/kcam/kcamd

This GDB was configured as “–host=x86_64-linux-gnu –target=mipsel-openwrt-linux-uclibc”.

(gdb) b main
Breakpoint 1 at 0x400cac: file main.cpp, line 29.
(gdb) c
Continuing.
warning: `/usr/lib/libstdc++.so.6′: Shared library architecture unknown is not compatible with target architecture mips:isa32r2.
warning: `/lib/libgcc_s.so.1′: Shared library architecture unknown is not compatible with target architecture mips:isa32r2.
warning: Could not load shared library symbols for 5 libraries, e.g. /lib/libuci.so.
Use the “info sharedlibrary” command to see the complete listing.
Do you need “set solib-search-path” or “set sysroot”?

Breakpoint 1, (gdb) n
Remote ‘g’ packet reply is too long: 00000000f8ffffffecdee77740b4ff7701000000f46dff7ffc6dff7f2034847fec6eff7f000101819bffaaacf0ffffff00031c7fffffffff00000000c826e677da6eff7f1c094000406dff7f0098e477f8e0a0000e00000000004400dc7a430087040000900c40000000000000000000a013e877786aff7f786aff7f4c27e67713ff0001a070230029000000a0d1e17724008050ac0c4000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000
(gdb)

继续阅读…

使用distcc分布式编译加速Android NDK原生项目编译生成

随着项目规模的增大,源代码文件增多,结构越来越复杂,导致项目编译链接速度变慢是一件让人非常头痛的事!

在Windows上我们用Visual Studio可以使用IncrediBuild (http://www.incredibuild.com/) 这个非常好用的分布式编译工具,配合其自带的VS Add-In可以很方便的将大型项目的编译工作负担分布到网络上的其它机器完成,极大的缩短了项目编译时间,提高工作效率!

不过遗憾的是IncrediBuild目前只支持Windows系统和VS等一些编译环境,对于Android, iOS等交叉编译的移动平台开发环境就无能为力了。

其实对于linux系OS上还是有可用的分布式编译解决方案的,就是接下来我要说的这个distcc,项目介绍请猛击这里:https://code.google.com/p/distcc/

继续阅读…

Xcode升级后导致原Qt项目构建失败的问题

原有使用Qt Creator 4.0.2创建的跨平台GUI项目,在近日Xcode升级至8.0后,出现了构建失败的问题,错误信息如下:

clang: warning: no such sysroot directory: ‘/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk’
In file included from ../FbxVertexMerger/main.cpp:1:
In file included from ../FbxVertexMerger/mainwindow.h:4:
In file included from ../../../../Qt5.7.0/5.7/clang_64/lib/QtWidgets.framework/Headers/QMainWindow:1:
In file included from ../../../../Qt5.7.0/5.7/clang_64/lib/QtWidgets.framework/Headers/qmainwindow.h:43:
In file included from /Users/wzkres/Qt5.7.0/5.7/clang_64/lib/QtWidgets.framework/Headers/qwidget.h:43:
In file included from /Users/wzkres/Qt5.7.0/5.7/clang_64/lib/QtGui.framework/Headers/qwindowdefs.h:43:
In file included from /Users/wzkres/Qt5.7.0/5.7/clang_64/lib/QtCore.framework/Headers/qglobal.h:81:
/Users/wzkres/Qt5.7.0/5.7/clang_64/lib/QtCore.framework/Headers/qsystemdetection.h:95:12: fatal error: ‘TargetConditionals.h’ file not found
# include <TargetConditionals.h>

显然,问题出在MacOSX10.11.sdk这个位置,升级后的MacOSX SDK变为了MacOSX10.12.sdk,那么如何让Qt使用新版本的SDK呢?很简单,修改Qt项目的.pro文件,加入 继续阅读…