마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

JNI 외부 라이브러리(x264) 추가하려는데 조언부탁드립니다.

0 추천

안녕하세요, 영상관련 프로젝트 진행중입니다.

오픈소스(https://github.com/Teaonly/android-eye)를 참고하면서 개발하고 있는데 JNI 부분에서 외부 라이브러리 (x264)를 추가한 부분은 빠져있어서 애를 먹고 있습니다.

안드로이드에 JNI 추가하는 것도 처음인데 외부 라이브러리까지 추가하려다 보니 많이 벅차네요.

제가 지금 하고 있는 방향이 맞는지, 막히는 부분은 어찌해야할지 조언해주시면 감사하겠습니다.

 

[개발환경]

Window7 64bit (Intel i3)

Android Studio 1.5

Gradle Version : 2.4

- compileSdkVersion 23

- minSdkVersion 9

- targetSdkVersion 23

NDK(android-ndk-r10e-windows-x86_64): "D:\AndroidStuio\ndk"

JDK(JDK 1.8.0_45): "C:\Program Files\Java\jdk1.8.0_45"

 

1) javah, ndk-build 설정

안드로이드 스튜디오 상에서 javah, ndk-build 툴 설정을 해주었습니다.

 

2) MainAcitivy.java에서 native 라이브러리를 로드하는 함수도 구현했습니다.

3) 프로젝트/app/src/main/jni 폴더에는 오픈소스들이 이미 들어가있는 상태입니다.

 

 

안드로이드 스튜디오 터미널 창에서 다음과 같이 javah 명령어를 실행하여 생긴 헤더 파일은 jni폴더로 복사하여줬습니다.

저 헤더파일과 오픈소스의 .cpp파일을 연결해줘야 할 것 같은데 아래와 같이 한걸로 될지 모르겠습니다.

(헤더파일의 이름은 아래에 보시는 바와 같고, cpp파일은 main_jni.cpp입니다.)

 

4) Android.mk와 Applcation.mk는 오픈소스것 그대로 사용하였습니다.

Android.mk

(좌. Android.mk / 우. Application.mk)

 

5) Gradle 설정

gradle.properties 파일에 아래 항목을 추가했습니다.

 

build.gradle 파일을 아래와 같이 수정하였습니다.

import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.application'

def getNdkBuildPath() {
    Properties properties = new Properties()
    properties.load(project.rootProject.file('local.properties').newDataInputStream())

    def command =  properties.getProperty('ndk.dir')
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        command += "\\ndk-build.cmd"
    } else {
        command += "/ndk-build"
    }

    return command
}

android {
    sourceSets.main {
        // Compile된 Native Library가 위치하는 경로를 설정합니다.
        jniLibs.srcDir 'src/main/libs'

        // 여기에 JNI Source 경로를 설정하면 Android Studio에서 기본적으로 지원하는 Native
        // Library Build가 이루어집니다. 이 경우에 Android.mk와 Application.mk를
        // 자동으로 생성하기 때문에 편리하지만, 세부 설정이 어렵기 때문에 JNI Source의
        // 경로를 지정하지 않습니다.
        jni.srcDirs = []
    }

    ext {
        // 아직은 Task 내에서 Build Type을 구분할 방법이 없기 때문에 이 Property를
        // 이용해 Native Library를 Debugging 가능하도록 Build할 지 결정합니다.
        nativeDebuggable = false
    }

    // NDK의 ndk-build 명령을 이용하여 Native Library를 Build하기 위한 Task를 정의합니다.
    //noinspection GroovyAssignabilityCheck
    task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
        if (nativeDebuggable) {
            commandLine getNdkBuildPath(), 'NDK_DEBUG=1', '-C', file('src/main').absolutePath
        } else {
            commandLine getNdkBuildPath(), '-C', file('src/main').absolutePath
        }
    }

    // App의 Java Code를 Compile할 때 buildNative Task를 실행하여 Native Library도 같이
    // Build되도록 설정합니다.
    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn buildNative
    }

    // NDK로 생성된 Native Library와 Object를 삭제하기 위한 Task를 정의합니다.
    //noinspection GroovyAssignabilityCheck
    task cleanNative(type: Exec, description: 'Clean native objs and lib') {
        commandLine getNdkBuildPath(), '-C', file('src/main').absolutePath, 'clean'
    }

    // Gradle의 clean Task를 실행할 떄, cleanNative Task를 실행하도록 설정합니다.
    clean.dependsOn 'cleanNative'

    buildTypes {
        debug {
            // Debug Build시에 Native Library Debugging이 가능한 APK를 생성하도록 설정합니다.
            jniDebuggable true
        }
    }

    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "capstone.coelacanth.cameramockup"
        minSdkVersion 9
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile files('libs/java_websocket.jar')
}

 

6) RUN

이후 Run을 하면 당연히 아래와 같이 실패하게 됩니다.

 

에러 메세지에 나와있듯(x264/libx264.a)이 x264 라이브러리는 따로 받아야 하는 듯 하여 아래의 안내대로

git clone git://git.videolan.org/x264.git
export NDK_SYSROOT=~/opt/android-ndk-r9d/platforms/android-9/arch-arm
export PATH=$PATH:~/opt/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/
./configure --cross-prefix=arm-linux-androideabi- --sysroot="$NDK_SYSROOT" --host=arm-linux --enable-pic --enable-static --disable-cli
make STRIP=

시그윈을 설치한 뒤, 위 명령어 중 수정할 부분은 수정하여 그대로 입력하였습니다.

- 제가 git clone 받은 폴더는 D:\JS/x264 폴더입니다.

- NDK_SYSROOT는 D:\AndroidStudio/ndk/platforms/android-9/arch-arm 으로 입력했습니다.

- PATH는 $PATH:D:\AndroidStudio/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin으로 입력했습니다.

- 나머지는 그대로 입력하였는데, 시그윈이 에러를 뱉습니다.

에러는 총 두가지 경우입니다. No working C compiler found 라는 문구거나, 

아니면 아무 문구도 없이 그대로 멈춰버립니다.(절대 경로로 줘봤습니다)

 

 

질문이 장황하고 두서가 없는데, 크게 보면 4가지로 요약할 수 있겠네요.

1. 위의 작업 흐름이 맞는가

2. MainActivity.h와 기존 오픈소스의 main_jni.cpp의 연결방법

3. 위 처럼 Cygwin에서 빌드가 멈춰버리는 경우 해결법은...?

4. 빌드 성공시 생성되는 파일을 라이브러리로 추가하는 방법

 

작은 조언도 감사히 받겠습니다. 

ljs401 (120 포인트) 님이 2015년 11월 30일 질문

1개의 답변

0 추천
FYI: http://developer.android.com/intl/ko/ndk/guides/standalone_toolchain.html

# Problem:
    $ ./configure --enable-pic --enable-strip --enable-static --cross-prefix=/ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi- --sysroot=/ndk/platforms/android-9/arch-arm --host=arm-linux
    No working C compiler found.

# Solution:

//
// Create a standalone toolchain for x264 library.
//
x264 $ /ndk/build/tools/make-standalone-toolchain.sh --platform=android-9 --install-dir=/opt/ndk/x264_arm-linux-androideabi-4.6/prebuilt/windows
Auto-config: --toolchain=arm-linux-androideabi-4.6
Copying prebuilt binaries...
Copying sysroot headers and libraries...
Copying libstdc++ headers and libraries...
Copying files to: /opt/ndk/x264_arm-linux-androideabi-4.6/prebuilt/windows
Cleaning up...
Done.
x264 $

//
// PATH
//
export NDK=/opt/ndk/x264_arm-linux-androideabi-4.6/prebuilt/windows
//export NDK_SYSROOT=$NDK/sysroot
export PATH=$PATH:$NDK/bin

//
// Configure x264
// without option "--sysroot=..."
//
x264 $ ./configure --host=arm-linux --cross-prefix=arm-linux-androideabi- --enable-shared --enable-static --prefix=./ndk_output

x264 $ mkdir ndk_output

//
// Build
//
x264 $ make STRIP= && make install

 

// output directory
./ndk_output/

 

아, 참고로 x264 디렉토리에 "config.txt" 파일을 보시면 error details 가 있습니다.

i hope this may help you.
thanks

godmode2k
익명사용자 님이 2015년 11월 30일 답변
정말 감사합니다!
오늘 다른 컴퓨터에서 해보니 멈추는건 제 컴퓨터만 그렇더라구요.
조언해주신대로 다른 컴퓨터에서 해보고 다시 질문드리겠습니다^^
다시한번 감사드립니다
...