Windows环境下编译Android平台的libyuv

1. 说明

至于libyuv1的用途,就不赘述了。一下是官方说明

Scale YUV to prepare content for compression, with point, bilinear or box filter.
Convert to YUV from webcam formats for compression.
Convert to RGB formats for rendering/effects.
Rotate by 90/180/270 degrees to adjust for mobile devices in portrait mode.
Optimized for SSSE3/AVX2 on x86/x64.
Optimized for Neon on Arm.
Optimized for MSA on Mips

2. 编译过程

  当然你也可以放在Android Studio上编译。这里是脱离Android studio开发环境编译,直接编译好动、静态库和头文件,可以copy给其它库用。这样比在我们自己的库中依赖编译libyuv要节省编译时间。

2.1 下载

下载源码
https://chromium.googlesource.com/libyuv/libyuv/+archive/refs/heads/master.tar.gz

  现在最新版本是 1719,可以在下载的源码中include/libyuv/version.h查看版本号

2.2 稍改CMakeLists.txt脚本

  原本我们并不需要改变CMakeLists.txt脚本,只是为了存放目录,把动、静态库放在lib目录,头文件放在include目录。如果不改变脚本,编译后,自己手动copy也是可以的。
  最重要的就是,Android studio集成cmake编译,是在打包的时候才strip掉符号表。我们脱离Android studio开发环境,直接使用Cmake编译,不管是Release版本还是Debug版本,Cmake都没有Strip掉符号表,库会比较大,所以我们在脚本里定制一个command,直接strip掉符号表。一般我们不会debug开源库。所以没有必要保留开源库的符号表,当然你也可以保留,集成到其它的JNI库通过Android studio打包的时候gradle流程依然会strip掉符号表。

# CMakeLists for libyuv
# Originally created for "roxlu build system" to compile libyuv on windows
# Run with -DTEST=ON to build unit tests

PROJECT ( YUV C CXX )	# "C" is required even for C++ projects
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
OPTION( TEST "Built unit tests" OFF )

SET ( ly_base_dir	${PROJECT_SOURCE_DIR} )
SET ( ly_src_dir	${ly_base_dir}/source )
SET ( ly_inc_dir	${ly_base_dir}/include )
SET ( ly_tst_dir	${ly_base_dir}/unit_test )
SET ( ly_lib_name	yuv )
SET ( ly_lib_static	${ly_lib_name} )
SET ( ly_lib_shared	${ly_lib_name}_shared )

FILE ( GLOB_RECURSE	ly_source_files ${ly_src_dir}/*.cc )
LIST ( SORT			ly_source_files )

FILE ( GLOB_RECURSE	ly_unittest_sources ${ly_tst_dir}/*.cc )
LIST ( SORT			ly_unittest_sources )

INCLUDE_DIRECTORIES( BEFORE ${ly_inc_dir} )

# this creates the static library (.a)
ADD_LIBRARY				( ${ly_lib_static} STATIC ${ly_source_files} )

# this creates the shared library (.so)
ADD_LIBRARY				( ${ly_lib_shared} SHARED ${ly_source_files} )
SET_TARGET_PROPERTIES	( ${ly_lib_shared} PROPERTIES OUTPUT_NAME "${ly_lib_name}" )
SET_TARGET_PROPERTIES	( ${ly_lib_shared} PROPERTIES PREFIX "lib" )

# this creates the conversion tool
ADD_EXECUTABLE			( yuvconvert ${ly_base_dir}/util/yuvconvert.cc )
TARGET_LINK_LIBRARIES	( yuvconvert ${ly_lib_static} )


INCLUDE ( FindJPEG )
if (JPEG_FOUND)
  include_directories( ${JPEG_INCLUDE_DIR} )
  target_link_libraries( yuvconvert ${JPEG_LIBRARY} )
  add_definitions( -DHAVE_JPEG )
endif()

if(TEST)
  find_library(GTEST_LIBRARY gtest)
  if(GTEST_LIBRARY STREQUAL "GTEST_LIBRARY-NOTFOUND")
    set(GTEST_SRC_DIR /usr/src/gtest CACHE STRING "Location of gtest sources")
    if(EXISTS ${GTEST_SRC_DIR}/src/gtest-all.cc)
      message(STATUS "building gtest from sources in ${GTEST_SRC_DIR}")
      set(gtest_sources ${GTEST_SRC_DIR}/src/gtest-all.cc)
      add_library(gtest STATIC ${gtest_sources})
      include_directories(${GTEST_SRC_DIR})
      include_directories(${GTEST_SRC_DIR}/include)
      set(GTEST_LIBRARY gtest)
    else()
      message(FATAL_ERROR "TEST is set but unable to find gtest library")
    endif()
  endif()

  add_executable(libyuv_unittest ${ly_unittest_sources})
  target_link_libraries(libyuv_unittest ${ly_lib_name} ${GTEST_LIBRARY})
  find_library(PTHREAD_LIBRARY pthread)
  if(NOT PTHREAD_LIBRARY STREQUAL "PTHREAD_LIBRARY-NOTFOUND")
    target_link_libraries(libyuv_unittest pthread)
  endif()
  if (JPEG_FOUND)
    target_link_libraries(libyuv_unittest ${JPEG_LIBRARY})
  endif()

  if(NACL AND NACL_LIBC STREQUAL "newlib")
    target_link_libraries(libyuv_unittest glibc-compat)
  endif()

  find_library(GFLAGS_LIBRARY gflags)
  if(NOT GFLAGS_LIBRARY STREQUAL "GFLAGS_LIBRARY-NOTFOUND")
    target_link_libraries(libyuv_unittest gflags)
    add_definitions(-DLIBYUV_USE_GFLAGS)
  endif()
endif()

# ----------------------------------新加的内容-------------------------------------
# 为了是目录更明确,自己创建目录
if(NOT EXISTS CMAKE_INSTALL_PREFIX)
	message(WARNING "目录${CMAKE_INSTALL_PREFIX}-----not exists---------------")
	file(MAKE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/lib ${CMAKE_INSTALL_PREFIX}/include)
endif()

#copy头文件文件夹,动态库和静态库文件都放在lib目录,头文件放在include目录
add_custom_command( TARGET ${ly_lib_shared} POST_BUILD
                    COMMAND ${CMAKE_COMMAND} -E copy_directory ${ly_inc_dir} ${CMAKE_INSTALL_PREFIX}/include)

# strip动态库的符号表
add_custom_command( TARGET ${ly_lib_shared} POST_BUILD
                    COMMAND "${ANDROID_TOOLCHAIN_PREFIX}strip" "--strip-unneeded" "-o" 
				"${CMAKE_INSTALL_PREFIX}/lib/lib${ly_lib_name}-strip.so" "${CMAKE_INSTALL_PREFIX}/lib/lib${ly_lib_name}.so"
                    COMMENT "strip符号表")
# ---------------------------------------------------------------------------------

# install the conversion tool, .so, .a, and all the header files
INSTALL ( PROGRAMS ${CMAKE_BINARY_DIR}/yuvconvert			DESTINATION ${CMAKE_INSTALL_PREFIX}/bin )
INSTALL ( TARGETS ${ly_lib_static}					DESTINATION ${CMAKE_INSTALL_PREFIX}/lib )
INSTALL ( TARGETS ${ly_lib_shared} LIBRARY				DESTINATION lib RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin )
INSTALL ( DIRECTORY ${PROJECT_SOURCE_DIR}/include/		DESTINATION ${CMAKE_INSTALL_PREFIX}/include )

# create the .deb and .rpm packages using cpack
INCLUDE ( CM_linux_packages.cmake )

2.3 Windows环境编译脚本bat

@echo off
cls
::==========================================================================
::本脚本用来在Windows环境使用Cmake交叉编译Android使用的libyuv库
::==========================================================================

title cmake build libyuv

chcp 65001>nul

echo.
echo.
echo.--------本脚本用来用来在Windows环境使用Cmake交叉编译Android使用的库------
echo.

echo CMD Path:%cd%
echo 当前 dir:%~dp0

rem 切换到当前目录
cd /d %~dp0

:: --------------------------------------------------------------------------
rem 临时变量
set ANDROID_NDK=F:/Android/android-ndk-r16b
set CMAKE_PATH=D:/Android/android-sdk/cmake/3.6.4111459
set NASM_PATH=D:/Progra~1/Android/nasm-2.13.03
set ANDROID_VERSION=24
set SOURCE_DIR=./libyuv-refs_heads_master
set NATIVE_BUILD_DIR=.
set INSTALL_DIR=%~dp0

set ANDROID_ARMV5_CFLAGS="-march=armv5te"
rem -mfpu=vfpv3-d16  -fexceptions -frtti
set ANDROID_ARMV7_CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mfpu=neon"
rem -mfloat-abi=softfp -mfpu=neon -fexceptions -frtti
set ANDROID_ARMV8_CFLAGS="-march=armv8-a"   
set ANDROID_X86_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
set ANDROID_X86_64_CFLAGS="-march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel"

:: --------------------------------------------------------------------------
echo.
echo.--------------------------开始build--------------------------------------
echo.

rem call:label表示调用用":"标识,以goto:eof结束的函数代码段

rem --make armeabi
call:buildLibTurboJpeg armeabi %ANDROID_ARMV5_CFLAGS%

rem --make armeabi-v7a
call:buildLibTurboJpeg armeabi-v7a %ANDROID_ARMV7_CFLAGS%

rem --make arm64-v8a
call:buildLibTurboJpeg arm64-v8a %ANDROID_ARMV8_CFLAGS%

rem --make x86
call:buildLibTurboJpeg x86 %ANDROID_X86_CFLAGS%

rem --make x86_64
call:buildLibTurboJpeg x86_64 %ANDROID_X86_64_CFLAGS%

set timeout=5
echo.倒计时 %timeout% 秒钟后自动退出
for /L %%a in (%timeout% -1 1) do ( ^
	set /p=%%a . <nul&ping -n 2 127.0.0.1>nul
)

echo.
echo.&pause&goto:eof

:: --------------------------------------------------------------------------
rem 定义函数 (%1:arch_abi,%2:cflags)
:buildLibTurboJpeg
setlocal

	echo.[func]-----------------start make [%1]---------------------------
	echo.
	
	::注意这里我们使用  %~1 引用参数是为了脱去变量赋值时的 边界 双引号""
	set ABI=%~1
	set CFLAGS=%~2
	set BINARY_DIR="%NATIVE_BUILD_DIR%/bin/%ABI%"
	set PLATFORM_VERSION=%ANDROID_VERSION%
	set LIB_OUTPUT_DIR="%INSTALL_DIR%/dist/%ABI%"
	
	rem 批处理中if else 需在一行,() 括号内容表示在"("开始的同一行
	if %ABI%==armeabi (
		echo.[func]----当前编译--^>armeabi
		goto pass
	)
	if %ABI%==armeabi-v7a (
		echo.[func]----当前编译--^>armeabi-v7a
		goto pass
	)
	if %ABI%==arm64-v8a (
		echo.[func]----当前编译--^>arm64-v8a
		goto pass
	)
	if %ABI%==x86 (
		echo.[func]----当前编译--^>x86
		goto pass
	)
	if %ABI%==x86_64 (
		echo.[func]----当前编译--^>x86_64
		goto pass
	) else (
		echo.[ERROR]----不支持的ABI---^>%ABI%
		pause>nul
		exit
	)
	
	:pass
	
	echo [func]----PLATFORM_VERSION==%ANDROID_VERSION%
	echo [func]----ABI==%ABI%
	echo [func]----CFLAGS==%CFLAGS%
	echo [func]----SOURCE_DIR==%SOURCE_DIR%
	echo [func]----BINARY_DIR==%BINARY_DIR%
	echo [func]----LIB_OUTPUT_DIR==%LIB_OUTPUT_DIR%
	echo.
	echo.
	
	if not exist %BINARY_DIR% md %BINARY_DIR%
	
	cd /d %BINARY_DIR%
	
	:: -G"MinGW Makefiles"
	:: -DCMAKE_MAKE_PROGRAM=%ANDROID_NDK%/prebuilt/windows-x86_64/bin/make.exe
	
	rem 开源库有提供cmake 		Android Gradle - Ninja ^ 
	cmake ^
		-DANDROID_ABI=%ABI% ^
		-DANDROID_PLATFORM=android-%PLATFORM_VERSION% ^
		-DCMAKE_INSTALL_PREFIX=%LIB_OUTPUT_DIR% ^
		-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=%LIB_OUTPUT_DIR%/lib ^
		-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=%LIB_OUTPUT_DIR%/lib ^
		-DCMAKE_BUILD_TYPE=Release ^
		-DANDROID_NDK=%ANDROID_NDK% ^
		-DCMAKE_TOOLCHAIN_FILE=%ANDROID_NDK%/build/cmake/android.toolchain.cmake ^
		-DCMAKE_MAKE_PROGRAM=%CMAKE_PATH%/bin/ninja.exe ^
		-G"Android Gradle - Ninja" ^
		-DANDROID_ARM_NEON=TRUE ^
		-DANDROID_TOOLCHAIN=clang ^
		-DANDROID_STL=c++_static ^
		-DCMAKE_C_FLAGS="%CFLAGS% -Os -Wall -pipe -fPIC" ^
		-DANDROID_CPP_FEATURES=rtti exceptions ^
		../../%SOURCE_DIR%
		
	cmake --build ./
	rem ninja -C .
	
	cd ../../
			
	echo.[func]-----------------[%1] make end---------------------------
	echo.

endlocal
goto:eof

2.4 编译静态、动态库

  双击执行以上脚本保存的bat文件即可,等待编译完成
编译前
Windows环境下编译Android平台的libyuv_第1张图片
Windows环境下编译Android平台的libyuv_第2张图片
Windows环境下编译Android平台的libyuv_第3张图片
Windows环境下编译Android平台的libyuv_第4张图片


  1. https://chromium.googlesource.com/libyuv/libyuv/+/refs/heads/master ↩︎

你可能感兴趣的:(NDK,Android,JNI)