编译mono5.3的步骤和坑

编译mono是为了做unity3d游戏的dll加密

推荐在ubuntu下编译,windows上坑太多了而且搜不到几个有用的文章于是就放弃了

我在腾讯上架设的一个ubuntu16.04 64位的虚拟机

首先安装图形界面 说起了ubuntu的apt-get是一个很不错的东西,缺什么apt-get install xxx 然后输入y(yes)回车就ok

登录这个不用多说哈,然后给root用户添加一个固定密码,目前还木有安装图形化界面,都在终端操作

sudo passwd root

给root设置好密码之后呢开始装图形界面,我用的是gnome

首先在终端输入

sudo apt-get install gnome-session-flashback
然后y确认安装,装好之后呢切root用户,切的时候在终端su一下就ok

然后输入重启命令

reboot now

重启后就可以看到让人稀罕的图形界面了

然后输入用户名和密码登陆

编译mono5.3的步骤和坑_第1张图片    好了现在打开火狐浏览器

去mono的github下载相应的版本https://github.com/Unity-Technologies/mono

首先第一个坑:找不到准确与unity版本对应的mono

例如我的unity是5.3.4 mono版本却只有5.3 ,于是就拿5.3的编译

下载下来之后我们先解压,然后打开mono-unity-5.3/external/buildscripts中的build_runtime_android.sh

编译mono5.3的步骤和坑_第2张图片

然后我们去下载r10e版的ndk 切记要选r10e版本  ndk下载地址

等下载完了之后我们先把ndk解压出来

然后在终端输入

gedit .hashrc
然后在最下面加上自己ndk的路径

这里一定要填ANDROID_NDK_ROOT要不mono会找不到

之后在终端输入

source gedit .hashrc
即时生效我们所配置的变量,然后切到任意目录下测试下是否配置成功


然后我们通过终端安装所需的软件 autoconf automake libtool pkg-config  (输入sudo apt-get install softwarename即可)

安装完了之后,我们切入到unity-mono-5.3的文件夹

执行

./autogen.sh
来cheking下我们的mono中的文件和软件是否安装全了,如果提示没有xxx软件 就用apt-get install 安装

完成这一步之后在终端输入命令进入到builds文件夹

cd external
cd builds
然后把目录中的build_runtime_android.sh打开,引导一下ndk的路径,然后修改编译的版本(debug/正式)和编译的类型(armeabi-v7a/x86,编译的时候只要这两个)

首先我们来分析下这个代码的作用,这样后面遇到坑起码思绪不会特别乱

#!/bin/bash

# NB! Prereq : ANDROID_NDK_ROOT=/usr/local/android-ndk-xxx or similar
# Todo: set appropriate ARM flags for hard floats

export ANDROID_PLATFORM=android-9
//这里引导下ndk-r10e的版本路径,如果不引导的话就会报下面的错
export ANDROID_NDK_ROOT=/home/android-ndk-r10e
GCC_PREFIX=arm-linux-androideabi-
//gcc的版本要>=4.8,不然编译会提示找不到gcc或者c无法创建程序及
GCC_VERSION=4.8
//编译完成导出的路径
OUTDIR=builds/embedruntimes/android
CWD="$(pwd)"
PREFIX="$CWD/builds/android"
//build代码路径
BUILDSCRIPTSDIR=external/buildscripts
//会把ndk的路径存到envsetup.sh里,如果这个文件丢失可以手动建一个,里面放入export ANDROID_NDK_ROOT=/home/android-ndk-r10e即可
perl ${BUILDSCRIPTSDIR}/PrepareAndroidSDK.pl -ndk=r10e -env=envsetup.sh && source envsetup.sh
//根据ndk路径验证ndk是否存在
NDK_ROOT=`cd $ANDROID_NDK_ROOT && pwd`

if [ ! -f $NDK_ROOT/GNUmakefile ]; then
	echo "Failed to locate Android NDK; is ANDROID_NDK_ROOT correctly set?" //未能找到ANDROID_NDK_ROOT..... 正是对应前面的引导路径
	exit 1
fi
//检查所处的环境
HOST_ENV=`uname -s`
case "$HOST_ENV" in
    Darwin)
        HOST_ENV=darwin
        ;;
    Linux)
        HOST_ENV=linux
        ;;
    CYGWIN*|*_NT-*)
        HOST_ENV=windows
        ;;
	*)
		echo "Failed to locate supported host environment; HOST_ENV = $HOST_ENV ..."
		exit 1
		;;
esac

PLATFORM_ROOT=$NDK_ROOT/platforms/$ANDROID_PLATFORM/arch-arm
TOOLCHAIN=$NDK_ROOT/toolchains/$GCC_PREFIX$GCC_VERSION/prebuilt/$HOST_ENV
//当我们运行这个类后,会自己调起build_runtime_android_x86.sh
if [ ! -d $TOOLCHAIN ]; then
	TOOLCHAIN=${TOOLCHAIN}-x86
	if [ ! -d $TOOLCHAIN ]; then
		TOOLCHAIN=${TOOLCHAIN}_64
	fi
fi

if [ ! -a $TOOLCHAIN -o ! -a $PLATFORM_ROOT ]; then
	NDK_NAME=`basename $NDK_ROOT`
	echo "Failed to locate toolchain/platform; $NDK_NAME | $HOST_ENV | $GCC_PREFIX$GCC_VERSION | $ANDROID_PLATFORM"
	exit 1
fi
//这里要改掉
//原代码为 KRAIT_PATCH_PATH="${CWD}/../../android_krait_signal_handler/build" 
//改为 KRAIT_PATCH_PATH="${CWD}/android_krait_signal_handler/build" 
//然后这个文件夹就在mono的根目录下了,不过这个是自动从git上下载的,如果电脑没有安装git,还要再apt-get install git
KRAIT_PATCH_PATH="${CWD}/../../android_krait_signal_handler/build"
PATH="$TOOLCHAIN/bin:$PATH"
CC="$TOOLCHAIN/bin/${GCC_PREFIX}gcc --sysroot=$PLATFORM_ROOT"
CXX="$TOOLCHAIN/bin/${GCC_PREFIX}g++ --sysroot=$PLATFORM_ROOT"
CPP="$TOOLCHAIN/bin/${GCC_PREFIX}cpp"
CXXCPP="$TOOLCHAIN/bin/${GCC_PREFIX}cpp"
CPATH="$PLATFORM_ROOT/usr/include"
LD=$TOOLCHAIN/bin/${GCC_PREFIX}ld
AS=$TOOLCHAIN/bin/${GCC_PREFIX}as
AR=$TOOLCHAIN/bin/${GCC_PREFIX}ar
RANLIB=$TOOLCHAIN/bin/${GCC_PREFIX}ranlib
STRIP=$TOOLCHAIN/bin/${GCC_PREFIX}strip
CFLAGS="\
-DANDROID -DPLATFORM_ANDROID -DLINUX -D__linux__ \
-DHAVE_USR_INCLUDE_MALLOC_H -DPAGE_SIZE=0x1000 \
-D_POSIX_PATH_MAX=256 -DS_IWRITE=S_IWUSR \
-DHAVE_PTHREAD_MUTEX_TIMEDLOCK \
-fpic -g -funwind-tables \    //这里需要把g改成02
-ffunction-sections -fdata-sections"
CXXFLAGS=$CFLAGS
CPPFLAGS=$CFLAGS
LDFLAGS="\
-Wl,--wrap,sigaction \
-L${KRAIT_PATCH_PATH}/obj/local/armeabi -lkrait-signal-handler \
-Wl,--no-undefined \
-Wl,--gc-sections \
-Wl,-rpath-link=$PLATFORM_ROOT/usr/lib \
-ldl -lm -llog -lc"

CONFIG_OPTS="\
--prefix=$PREFIX \
--cache-file=android_cross.cache \
--host=arm-eabi-linux \
--disable-mcs-build \
--disable-parallel-mark \
--disable-shared-handles \
--with-sigaltstack=no \
--with-tls=pthread \
--with-glib=embedded \
--enable-nls=no \
mono_cv_uscore=yes"

if [ ${UNITY_THISISABUILDMACHINE:+1} ]; then
        echo "Erasing builds folder to make sure we start with a clean slate"
        rm -rf builds
fi

function clean_build_krait_patch
{		
		//从git上现在krait-signal-handler
       local KRAIT_PATCH_REPO="git://github.com/Unity-Technologies/krait-signal-handler.git"
       if [ ${UNITY_THISISABUILDMACHINE:+1} ]; then
               echo "Trusting TC to have cloned krait patch repository for us"
       elif [ -d "$KRAIT_PATCH_PATH" ]; then
               echo "Krait patch repository already cloned" //如果存在,就提示已经克隆下来了
       else
               git clone --branch "master" "$KRAIT_PATCH_REPO" "$KRAIT_PATCH_PATH"
       fi
       (cd "$KRAIT_PATCH_PATH" && ./build.pl)
}

function clean_build
{
	make clean && make distclean
	rm android_cross.cache

	pushd eglib
	autoreconf -i
	popd
	autoreconf -i

	./configure $CONFIG_OPTS \
	PATH="$PATH" CC="$CC" CXX="$CXX" CPP="$CPP" CXXCPP="$CXXCPP" \
	CFLAGS="$CFLAGS $1" CPPFLAGS="$CPPFLAGS $1" CXXFLAGS="$CXXFLAGS $1" LDFLAGS="$LDFLAGS $2" \
	LD=$LD AR=$AR AS=$AS RANLIB=$RANLIB STRIP=$STRIP CPATH="$CPATH"

	if [ "$?" -ne "0" ]; then 
		echo "Configure FAILED!" //编译失败,., 会显示出产生的错误
		exit 1
	fi

	make && echo "Build SUCCESS!" || exit 1 //编译成功之后会在mono根目录的build目录下生成so

	mkdir -p $3
	cp mono/mini/.libs/libmono.a $3
	cp mono/mini/.libs/libmono.so $3
}

CCFLAGS_ARMv5_CPU="-DARM_FPU_NONE=1 -march=armv5te -mtune=xscale -msoft-float"
CCFLAGS_ARMv6_VFP="-DARM_FPU_VFP=1  -march=armv6 -mtune=xscale -msoft-float -mfloat-abi=softfp -mfpu=vfp -DHAVE_ARMV6=1"
CCFLAGS_ARMv7_VFP="-DARM_FPU_VFP=1  -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -DHAVE_ARMV6=1"
LDFLAGS_ARMv5=""
LDFLAGS_ARMv7="-Wl,--fix-cortex-a8"

rm -rf $OUTDIR

clean_build_krait_patch

//这里要注释掉,否则编译速度会慢很多,而且我们只是需要armv7a和x86版本的so
//clean_build "$CCFLAGS_ARMv5_CPU" "$LDFLAGS_ARMv5" "$OUTDIR/armv5"
//clean_build "$CCFLAGS_ARMv6_VFP" "$LDFLAGS_ARMv5" "$OUTDIR/armv6_vfp"
clean_build "$CCFLAGS_ARMv7_VFP" "$LDFLAGS_ARMv7" "$OUTDIR/armv7a"

# works only with ndk-r6b and later
source ${BUILDSCRIPTSDIR}/build_runtime_android_x86.sh dontclean

NUM_LIBS_BUILT=`ls -AlR $OUTDIR | grep libmono | wc -l`
if [ $NUM_LIBS_BUILT -eq 8 ]; then
	echo "Android STATIC/SHARED libraries are found here: $OUTDIR"
else
	echo "Build failed? Android STATIC/SHARED library cannot be found... Found $NUM_LIBS_BUILT libs under $OUTDIR"
	ls -Al $OUTDIR
	exit 1
fi



在x86的文章中只去掉-g就ok

CFLAGS="\
-DANDROID -DPLATFORM_ANDROID -DLINUX -D__linux__ \
-DHAVE_USR_INCLUDE_MALLOC_H -DPAGE_SIZE=0x1000 \
-D_POSIX_PATH_MAX=256 -DS_IWRITE=S_IWUSR \
-DHAVE_PTHREAD_MUTEX_TIMEDLOCK \
-fpic -g \   //-g去掉
-ffunction-sections -fdata-sections"

然后打开PrepareAndroidSDK.pm,修改掉里头的验证,如果不改的话,会出现mono识别不出来r10e版的ndk从而编译一次下载一次炒鸡麻烦!!


编译mono5.3的步骤和坑_第3张图片

我们需要把这个改成

my @curr_arr=split(/\-|\s/,$current);  这样mono就认得r10e版本的ndk了

之后把build_runtime_android.sh拽到终端运行,如果提示xxx permission就先输入sudo然后在把文件拽过去运行

然后打开我们后面git下载的目录

编译mono5.3的步骤和坑_第4张图片

替换完了之后,我们打开build.pl

编译mono5.3的步骤和坑_第5张图片

如果直接运行可能会报这两个错

第一是

BEGIN failed--compilation aborted at external/buildscripts/PrepareAndroidSDK.pl line 10.
/usr/bin/env: perl -w: No such file or directory
第二是
checking whether the C compiler works... no
configure: error: in `/root/unity/mono-unity-5.3':
configure: error: C compiler cannot create executables
See `config.log' for more details
Configure FAILED!
第二应该是大部分人遇到的问题

所以要在这里修改好编译mono5.3的步骤和坑_第6张图片

如果没有别的意外,到最后便可以看到Build Success!

怎么加密我就不多说了老司机都懂!, 萌新们,可以看下雨凇和陆泽西以及Macgou的帖子

陆泽西重新编译Mono加密dll

雨凇Mono加密教程

U3D加密记事

Unity加密记事1

U3D加密记事2

U3D加密记事3



你可能感兴趣的:(开发中遇到的坑)