Android NDK ninja error "missing and no known rule to make it"

Viewed 3421

I'm trying to build a sample app from Occipital camera, which connects via USB to a Android device.

I imported their "out of box" sample app & attempted to build it.

However, Im getting a build command failed:

ninja: error: 'C:/Users/Fsydn/Desktop/occipital/StructureSDK-CrossPlatform-0.7.3-ROS/Libraries/MyOccipitalTestApp/app/src/main/app/lib/arm64-v8a/libstructure.so', needed by 'C:/Users/Fsydn/Desktop/occipital/StructureSDK-CrossPlatform-0.7.3-ROS/Libraries/MyOccipitalTestApp/app/build/intermediates/cmake/debug/obj/arm64-v8a/libMainActivity.so', missing and no known rule to make it

Below is all the source code & build files.

Java MainActivity:

package com.example.myoccipitaltestapp;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.os.Bundle;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.usb.UsbDeviceConnection;
import android.Manifest;

import android.opengl.GLSurfaceView;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.EGLConfig;

public class MainActivity extends Activity implements com.example.myoccipitaltestapp.StructureCoreUSBHelper.Delegate, ActivityCompat.OnRequestPermissionsResultCallback {
    private class GLRenderer implements GLSurfaceView.Renderer {
        private MainActivity owner;
        private int width;
        private int height;

        public GLRenderer(MainActivity owner) {
            this.owner = owner;
        }

        public void onSurfaceCreated(GL10 gl, EGLConfig config) {}

        public void onSurfaceChanged(GL10 gl, int width, int height) {
            this.width = width;
            this.height = height;
        }

        public void onDrawFrame(GL10 gl) {
            owner.renderFrame(width, height, owner.scaleFactor);
        }
    }

    private class GLView extends GLSurfaceView {
        private MainActivity owner;
        private boolean mouseDown;

        public GLView(Context context, MainActivity owner) {
            super(context);
            this.owner = owner;
        }

        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX();
            float y = event.getY();
            switch (event.getActionMasked()) {
                case MotionEvent.ACTION_DOWN:
                    mouseDown = true;
                    owner.updateMouseState(mouseDown, (int)x, (int)y);
                    return true;

                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    mouseDown = false;
                    owner.updateMouseState(mouseDown, (int)x, (int)y);
                    return true;

                case MotionEvent.ACTION_MOVE:
                    owner.updateMouseState(mouseDown, (int)x, (int)y);
                    return true;

                default:
                    return false;
            }
        }
    }

    private GLView glView;
    private volatile float scaleFactor = 1.f;
    private com.example.myoccipitaltestapp.StructureCoreUSBHelper usbHelper;

    private float computeScaleFactor() {
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        return metrics.density;
    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setupApp();

        scaleFactor = computeScaleFactor();
        glView = new GLView(this, this);
        glView.setEGLContextClientVersion(3);
        glView.setPreserveEGLContextOnPause(true);
        glView.setRenderer(new GLRenderer(this));
        glView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
        setContentView(glView);

        usbHelper = new com.example.myoccipitaltestapp.StructureCoreUSBHelper(this, this);
    }

    protected void onDestroy() {
        super.onDestroy();
        teardownApp();
    }

    public void onConfigurationChanged(Configuration config) {
        super.onConfigurationChanged(config);
        scaleFactor = computeScaleFactor();
        glView.requestRender();
    }

    protected void onPause() {
        super.onPause();
        glView.onPause();
    }

    protected void onResume() {
        super.onResume();
        glView.onResume();
        ActivityCompat.requestPermissions(this, new String[] {
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
        }, 1);
    }

    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    }

    public void newStructureCoreDevice(UsbDeviceConnection conn) {
        plugStructureCoreFileDescriptor(conn.getFileDescriptor());
    }


    static {

        System.loadLibrary("structure");
        System.loadLibrary("MainActivity");

    }

    private native void setupApp();
    private native void teardownApp();
    private native void renderFrame(int currentWidth, int currentHeight, float scaleFactor);
    private native void updateMouseState(boolean down, int x, int y);
    private native void plugStructureCoreFileDescriptor(int fd);
}

C++ MainActivity.cpp

// Autogenerated, do not edit

#include "AppInterface.h"
#include <jni.h>
#include <thread>

extern "C" JNIEXPORT void JNICALL Java_com_occipital_MyOccipitalTestApp_MainActivity_setupApp(JNIEnv *, jobject) {
    AppInterface::setup();
}

extern "C" JNIEXPORT void JNICALL Java_com_occipital_MyOccipitalTestApp_MainActivity_teardownApp(JNIEnv *, jobject) {
    AppInterface::teardown();
}

extern "C" JNIEXPORT void JNICALL Java_com_occipital_MyOccipitalTestApp_MainActivity_renderFrame(JNIEnv *, jobject, jint currentWidth, jint currentHeight, jfloat scaleFactor) {
    AppInterface::renderFrame((unsigned)currentWidth, (unsigned)currentHeight, scaleFactor);
}

extern "C" JNIEXPORT void JNICALL Java_com_occipital_MyOccipitalTestApp_MainActivity_updateMouseState(JNIEnv *, jobject, jboolean down, jint x, jint y) {
    AppInterface::updateMouseState(down, x, y);
}

extern "C" JNIEXPORT void JNICALL Java_com_occipital_MyOccipitalTestApp_MainActivity_plugStructureCoreFileDescriptor(JNIEnv *, jobject, jint fd) {
    AppInterface::plugStructureCoreFileDescriptor(fd);
}

AppInterface.h:

#pragma once

/** These functions define the interface between cross-platform sample
    application code and platform-specific wrappers. */
namespace AppInterface {
    /** On desktop platforms this function is called in main() before
        runUntilWindowClosed(). On Android it is called when the main activity
        is created. */
    void setup();

    /** On desktop platforms this function is called in main() after
        runUntilWindowClosed(). On Android it is called when the main activity
        is destroyed. */
    void teardown();

#if __ANDROID__
    /** See Window::renderFrameInGLSurfaceViewContext(). */
    void renderFrame(unsigned currentWidth, unsigned currentHeight, float scaleFactor);

    /** See Window::updateMouseState(). */
    void updateMouseState(bool down, int x, int y);

    /** For applications that require Structure Core USB support. The argument
        is a file descriptor from the Android UsbDeviceConnection API and should
        be passed to ST::registerSensorByUSBFileDescriptor() or equivalent. */
    void plugStructureCoreFileDescriptor(int fd);
#else
    /** Called in main(). */
    void runUntilWindowClosed();
#endif
}

Gradle build:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "com.example.myoccipitaltestapp"
        minSdkVersion 16
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        sourceSets {
            main {
                jniLibs.srcDir 'lib'
            }
        }

ndk{
    abiFilters  "arm64-v8a", "x86", "x86_64"
}

        externalNativeBuild {
            cmake {
                abiFilters  "arm64-v8a", "x86", "x86_64"
                arguments '-DANDROID_TOOLCHAIN=g++', '-DANDROID_STL=c++_shared', '-DANDROID_PLATFORM=android-24', '-DANDROID_STL=c++_static'
                cppFlags '-std=c++11'
            }
        }



    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }


    externalNativeBuild {
        cmake {
            path 'src/main/CMakeLists.txt'

        }
    }


}

dependencies {
    implementation fileTree(dir: 'lib', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

AndroidManifest.xml:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
</application>

CMakeLists.txt , The missing .so file is actually listed here in the CMake

# Autogenerated, do not edit

cmake_minimum_required(VERSION 3.6)
project(MainActivity)
add_library(MainActivity SHARED  C:/Users/Fsydn/Desktop/occipital/StructureSDK-CrossPlatform-0.7.3-ROS/Libraries/MyOccipitalTestApp/app/src/main/cpp/MainActivity.cpp)
set_target_properties(MainActivity PROPERTIES LINK_FLAGS "-Wl,-rpath,'$ORIGIN'")
target_link_libraries(MainActivity PRIVATE ${PROJECT_SOURCE_DIR}/app/lib/${ANDROID_ABI}/libstructure.so 
)

The actual project's file structure seems to correspond to ${PROJECT_SOURCE_DIR}/app/lib/${ANDROID_ABI}/libstructure.so path that is included in the CMake, see below:

enter image description here How can I build this app successfully?

Thanks a million.

0 Answers
Related