Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
173 views
in Technique[技术] by (71.8m points)

c++ - Minimal CMake building for android

I'm trying to port a native C++ DLL to be a shared library on Android. For building, I am using VSCode, not using Visual Studio. Downloaded the Android NDK r18b. My project is CMake based, and when I try to generate it to be with the "NMake Mmakefiles" generator, I always get this error:

CMAKE_SYSTEM_NAME is 'Android' but 'NVIDIA Nsight Tegra Visual Studio Edition' is not installed.

I have created a small project to test this.

main.cpp

int foo( int a, int b ) { return a + b; }

CMakeLists.txt

cmake_minimum_required( VERSION 3.11.0 )
add_library( Engine SHARED main.cpp )

I run it with this command line (CMake 3.11.4):

cmake -g "NMake Makefiles" .. -DCMAKE_TOOLCHAIN_FILE=%NDK_ROOT%uildcmakeandroid.toolchain.cmake -DANDROID_NDK=%NDK_ROOT%

With this one, I still get the error:

CMake Error in CMakeLists.txt:
CMAKE_SYSTEM_NAME is 'Android' but 'NVIDIA Nsight Tegra Visual Studio Edition' is not installed.

Can someone help me to make this small main.cpp into an Android .so? I'd not like to use Android Studio nor an other IDE. Looking for creating a make file and add it to my VSCode build.

Thank you.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In case you were willing to use Gradle to configure your cmake...

I use the Gradle Wrapper, after you install gradle you can call gradle wrapper in a directory and it will install a local copy. This copy can be set at a specific version or can be upgraded.

The Android Gradle plugin uses the ninja build system to configure cmake and target ABIs. The following scripts will generate ABIs for all supported platform types, but it is easy to remove any that you don't wish to create.

VSCode has a gradle plugin for generating from the IDE, or you can create a build type that simply calls the gradlew command line.


First, I inited a gradle project using gradle wrapper and then gradlew init.

Then I added the build scripts for building an Android Library.

build.gradle

/*
 * This file was generated by the Gradle 'init' task.
 *
 * This is a general purpose Gradle build.
 * Learn how to create Gradle builds at https://guides.gradle.org/creating-new-gradle-builds/
 */
 buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
        google()
    }
}

apply plugin: 'com.android.library'

android {
    compileSdkVersion 28      // Change this to the SDK version you have installed
    buildToolsVersion '28.0.3' // Change this to the SDK build tools you have installed
    defaultConfig {
        minSdkVersion 16      // Cannot be less than 16
        targetSdkVersion 28   // Same as CompileSdkVersion
        versionCode 1
        versionName "1.0"

        sourceSets {
            main {
                manifest.srcFile 'AndroidManifest.xml'
            }
        }

        ndk {
            abiFilters = []
            abiFilters.addAll(ABI_FILTERS.split(';').collect { it as String })
        }

        externalNativeBuild {
            cmake {
                arguments '-DANDROID_PLATFORM=android-16',
                        '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=c++_static',
                        '-DANDROID_CPP_FEATURES=rtti exceptions'
            }
        }

    }
    externalNativeBuild {
        cmake {
            path './CMakeLists.txt'
        }
    }
    buildTypes {
        release {
            minifyEnabled false
        }
        debug {
            debuggable true
            jniDebuggable true
            minifyEnabled false
        }
    }
}

This build file includes a dummy AndroidManifest.xml file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="16" />

    <application/>

</manifest>

I needed an older version of CMake, I went with 3.4 instead of 3.11

CMakeLists.txt

cmake_minimum_required( VERSION 3.4.0 )
add_library( Engine SHARED main.cpp )

local.properties

# This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
ndk.dir=d:\android\ndk
sdk.dir=d:\android\sdk

gradle.properties

# Project-wide Gradle settings.

# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.

# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html

# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m

# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

# EDIT THIS LINE to change the Target ABIs
ABI_FILTERS=x86;x86_64;armeabi-v7a;arm64-v8a

org.gradle.java.home=D:\Program Files\Java\jdk8

distributionUrl=
  https://services.gradle.org/distributions/gradle-4.1-all.zip

# When set to true the Gradle daemon is used to run the build. For local developer builds this is our favorite property.
# The developer environment is optimized for speed and feedback so we nearly always run Gradle jobs with the daemon.
org.gradle.daemon=true

Finally, to build I simply run:

.gradlew :externalNativeBuildDebug

or

.gradlew :externalNativeBuildRelease

And it generates the libraries in the buildintermediatescmake directory.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...