diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 42ed7d35a02..c813b048d74 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1,24 +1,25 @@ name: nightly-linux64 -on: - push: - paths-ignore: - - "**/*.md" - - "examples/**" - pull_request: - paths-ignore: - - "**/*.md" - - "examples/**" - +# #used for testing the nightly # on: -# schedule: -# - cron: "0 6 * * *" -# workflow_dispatch: -# inputs: -# release: -# description: 'release' -# required: true -# default: 'latest' +# push: +# paths-ignore: +# - "**/*.md" +# - "examples/**" +# pull_request: +# paths-ignore: +# - "**/*.md" +# - "examples/**" + +on: + schedule: + - cron: "0 6 * * *" + workflow_dispatch: + inputs: + release: + description: 'release' + required: true + default: 'latest' env: ccache: ccache RELEASE: latest @@ -65,4 +66,4 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} tag_name: "nightly" - files: ${{ steps.createpackage.outputs.FILES_OUT }} + files: out/of_v*.{tar.gz,zip} diff --git a/.github/workflows/of.yml b/.github/workflows/of.yml index 5bb244372a1..c47b78295e5 100644 --- a/.github/workflows/of.yml +++ b/.github/workflows/of.yml @@ -453,24 +453,51 @@ jobs: env: DEVELOPER_DIR: "/Applications/Xcode.app/Contents/Developer" SDKROOT: "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk" -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - build-android: + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + build-android: runs-on: ubuntu-24.04 strategy: matrix: cfg: - - { target: android, opt: arm64 } + - { target: android, opt: arm64-v8a } + - { target: android, opt: x86_64 } + - { target: android, opt: armeabi-v7a } + env: - TARGET: ${{matrix.cfg.target}} + TARGET: ${{ matrix.cfg.target }} + ARCH: ${{ matrix.cfg.opt }} + ANDROID_SDK_ROOT: $ANDROID_HOME + ANDROID_NDK_ROOT: $ANDROID_NDK_LATEST_HOME + steps: + - name: checkout openFrameworks + uses: actions/checkout@v4 - - uses: actions/checkout@v4 - # - name: ccache - # uses: hendrikmuhs/ccache-action@v1.2.14 - # with: - # key: ${{ matrix.cfg.target }}-${{ matrix.cfg.libs }} + - name: Set Up JDK 17 + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' - - name: Download libs - run: ./scripts/android/download_libs.sh -t $RELEASE + - name: Download Libraries + run: ./of update libs android + + + - name: Build openFrameworks Core - Debug + run: | + cd libs/openFrameworksCompiled/project/android/ + gradle wrapper + chmod +x gradlew + ./gradlew assembleDebug + + - name: Check if openFrameworks output Exists + run: | + LIB_PATH="libs/openFrameworksCompiled/lib/android/${ARCH}/libopenFrameworksAndroid.so" + if [ -f "$LIB_PATH" ]; then + echo "Build Success - [$LIB_PATH]" + else + echo "ERROR: Build Failed not found: [$LIB_PATH]" + exit 1 + fi diff --git a/docs/android_studio.md b/docs/android_studio.md index 8040a0fe387..654294b3426 100644 --- a/docs/android_studio.md +++ b/docs/android_studio.md @@ -1,6 +1,6 @@ [openFrameworks](http://openframeworks.cc/) | [Documentation table of contents](table_of_contents.md) -Android Studio +Android Studio 2025 ======= The Android distribution of openFrameworks is setup to work with Android Studio IDE. @@ -9,9 +9,17 @@ The Android distribution of openFrameworks is setup to work with Android Studio Setting up openFrameworks with Android Studio is fairly straightforward. The basic steps are: -- Install the latest version of [Android Studio](https://developer.android.com/studio/index.html) (tested with version 3.0). -- Download openFrameworks 0.10.0 or later from the [download page](http://openframeworks.cc/download/) or from [github](https://github.com/openframeworks/openFrameworks/). -- Download and unzip the Android NDK version r15c: [Windows](https://dl.google.com/android/repository/android-ndk-r15c-windows-x86_64.zip), [Linux](https://dl.google.com/android/repository/android-ndk-r15c-linux-x86_64.zip), [OSX](https://dl.google.com/android/repository/android-ndk-r15c-darwin-x86_64.zip). It doesn't matter where you store the library, you will point Android Studio to this location later. *Notice that openFrameworks only works with version r15c!* +- Install the latest version of [Android Studio](https://developer.android.com/studio/index.html) (tested with Android Studio Meerkat | 2024.3.1). + +### Select the following to be installed in SDK Manager (options) +- Android SDK 36.0 (or latest) - add any older APIs if targetting +- Build Tools 36.0.0 (or latest) +- NDK 28.0.13004108 (Side by Side) +- Android SDK Command Line Tools 19.0 (or latest) +- CMake 3.31.6 (or latest) + +## Install openFrameworks +- Download openFrameworks 0.12.1 or later from the [download page](http://openframeworks.cc/download/) or from [github](https://github.com/openframeworks/openFrameworks/). - If you got openFrameworks from git: - Run `scripts/android/download_libs.sh` to download libraries. - Use the Project Generator to generate Android Studio project files for android examples. @@ -22,7 +30,11 @@ Setting up openFrameworks with Android Studio is fairly straightforward. The bas ### Build and run -Press the Play button next to the `androidEmptyExample` shown in the toolbar. With any luck, it should build the app and deploy it to your Android device after a few seconds (or prompt you to deploy it to a suitable emulator). If the app runs, congratulations! You have setup openFrameworks. +Press the Play button next to the `androidEmptyExample` shown in the toolbar. It will build the app and deploy it to your Android device after a few seconds (or prompt you to deploy it to a suitable emulator). If the app runs, congratulations! You have setup openFrameworks. + +### Building directly with Gradle +- Can build directly in folder with ./gradlew assembleDebug +- System will need latest version of JDK for this https://www.oracle.com/us/java/technologies/downloads/#jdk23-mac ## Creating new projects diff --git a/libs/openFrameworksCompiled/project/android/common-functions.gradle b/libs/openFrameworksCompiled/project/android/common-functions.gradle deleted file mode 100755 index 11ba83a4473..00000000000 --- a/libs/openFrameworksCompiled/project/android/common-functions.gradle +++ /dev/null @@ -1,369 +0,0 @@ -// -//def getFilesRecursive(path){ -// FileTree tree = fileTree(dir: path) -// def files = tree.matching({includes ["*.cpp"]}).toList() -// return files -//} -// -//def getFoldersRecursive(String path){ -// def file = new File(path) -// def ret = [path] -// if(!file.exists()) return [] -// -// file.eachDirRecurse() { dir -> -// ret.add(dir.getAbsolutePath()) -// } -// return ret -// -//} -// -// -// -//def addonPaths(ofRoot){ -// def file = new File('addons.make') -// if(!file.exists()) { -// return [] -// } -// -// def addonRoot = ofRoot+"addons/" -// -// def ret = [] -// file.eachLine { line -> -// def folder = new File(addonRoot+line) -// if (!folder.exists()) { -// throw new GradleException("Addon ${line} could not be found at ${folder.absolutePath}") -// } -// ret += folder.absolutePath -// } -// -// return ret -//} -// -// -// -//def parseAddonConfig(String addon, String param, String abi, defaultVal = []){ -// def ret = defaultVal -// -// def file = new File(addon+"/addon_config.mk") -// if(!file.exists()){ -// println addon+"/addon_config.mk not found" -// return defaultVal -// } -// -// def mode = "" -// -// file.eachLine { line -> -// def stripLine = line.replaceAll("^\\s*","").replaceAll("\\s*\$","") -// if(stripLine.startsWith("#") || stripLine.length() == 0){ -// return -// } -// -// if(stripLine.endsWith(":")){ -// mode = stripLine.replaceAll(":\$","") -// } -// -// if(mode == "common" || mode == "android" || mode == "android/${abi}".toString()){ -// def group = (stripLine =~ /^(\w+)\s*(\+?=)\s*(.+)$/) -// if(group.hasGroup() && group.size() == 1 && group[0].size() == 4){ -// if(group[0][1] == param) { -// def _p = group[0][3].replaceAll("%", "*") -// if (group[0][2] == '=') { -// ret = [_p] -// } else { -// ret += _p -// } -// } -// } -// -// } -// } -// -// return ret -//} -// -//def addonSources(String root, String abi=""){ -// -// def ret = [] -// addonPaths(root).each { String addon -> -// def config = parseAddonConfig( -// addon, -// "ADDON_SOURCES", -// abi, -// ["src", "libs"] -// ) -// -// //ret += addon -// config.each { String path -> -// ret += addon+'/'+path -// } -// } -// println "\n\n ADDON_SOURCES "+ret+"\n\n" -// -// return ret -//} -// -//def addonIncludes(String root, String abi=""){ -// def ret = [] -// return ret -//} -// -//def addonSourcesExclude(String root, String abi=""){ -// def ret = [] -// addonPaths(root).each { String addon -> -// def config = parseAddonConfig( -// addon, -// "ADDON_SOURCES_EXCLUDE", -// abi -// ) -// -// config.each { String path -> -// // TODO: Currently first part of path is stripped. Doesn't work otherwise -// ret += path.replaceAll(/^\w+\//,"**/") -// } -// } -// -//// ret += "**/dlib/include/*" -// println "\n EXCLUDE "+ret+"\n\n" -// return ret -//} -// -// -//def addonLdFlags(abi, ofRoot){ -// def ret = [] -// addonPaths(ofRoot).each { String addon -> -// def libs = []; -// fileTree(dir: addon + "/libs", include: "**/lib/android/" + abi + "/*.a") -// .each{ lib -> libs += lib.getAbsolutePath(); }; -// -// def config = parseAddonConfig( -// addon, -// "ADDON_LIBS", -// abi, -// libs -// ) -// -// config.each { String path -> -// def f = new File(addon+"/"+path) -// if(f.exists()) { -// ret += f.toString(); -// } -// } -// } -// println "\n ADDON_LIBS "+ret+"\n\n" -// return ret -//} -// -// -// -//def addonCppFlags(abi, ofRoot){ -// def ret = [] -// addonPaths(ofRoot).each { addon -> -// def config = parseAddonConfig( -// addon, -// "ADDON_INCLUDES", -// abi, -// ["libs","src"] -// ) -// def excludeConfig = parseAddonConfig( -// addon, -// "ADDON_INCLUDES_EXCLUDE", -// abi -// ) -// -// config.each { String path -> -// def flags = [] -// getFoldersRecursive(addon+"/"+path).each{ String folder -> -// def excluded = false -// excludeConfig.each { ex -> -// def _ex = ex.replaceAll(/\*/,".+") -// if(folder ==~ /.*$addon\/$_ex/ ) { -// excluded = true -// } -// } -// -// if(!excluded) { -// flags += "-I${folder}".toString() -// } -// } -// -// ret += flags -// } -// -// -// def configFlags = parseAddonConfig(addon, "ADDON_CFLAGS", abi); -// configFlags.each { String flag -> -// ret += flag -// } -// -// /* -// ret += getFoldersRecursive(addon + "/libs").collect{ folder -> -// return "-I${folder}".toString() -// } -// ret += getFoldersRecursive(addon + "/src").collect{ folder -> -// return "-I${folder}".toString() -// }*/ -// } -// println "\n ADDON_CFLAGS "+ret+"\n\n" -// return ret -//} -// -//def addonData(ofRoot){ -// def ret = [] -// addonPaths(ofRoot).each { addon -> -// def configFlags = parseAddonConfig(addon, "ADDON_DATA", ""); -// configFlags.each { String path -> -// ret += addon + "/" + path -// } -// } -// return ret -//} -// -//def addonJavaDependencies(root,abi=""){ -// def ret = [] -// addonPaths(root).each { String addon -> -// def config = parseAddonConfig( -// addon, -// "ADDON_ANDROID_LIBS", -// abi -// ) -// -// config.each { String path -> -// def f = new File(addon+"/"+path) -// if(f.exists()) { -// ret += [[f.toString(), ':'+new File(addon).name]] -// } -// } -// } -// println "\n JAVA_LIBS "+ret+"\n\n" -// return ret -//} -// -//def javaDependencies(ofRoot){ -// def ret = [] -// ret += [[ofRoot+'addons/ofxAndroid/ofAndroidLib', ':ofAndroidLib']] -// ret += [[ofRoot+'libs/openFrameworksCompiled/project/android', ':openFrameworksProject']] -// return ret -//} -// -// -//def getFlavorName(abi) { -// switch (abi) { -// case "armeabi": -// return "armeabi"; -// case "armeabi-v7a": -// return "arm7" -// case "arm64-v8a": -// return "arm64" -// default: -// return abi.replaceAll('-', '_') -// } -//} -// -//def getAbis(){ -// return ["arm64-v8a", "armeabi-v7a", "x86"] -//} -// -//def ofAppModuleName(){ -// return "OFAndroidApp" -//} -// -//def buildToolchain(){ -// return "clang" -//} -// -//def appSrcDirs(ofRoot){ -// def ret = ['src', -// ofRoot+"/addons/ofxAndroid/src", -// ofRoot+"/addons/ofxAccelerometer/src" -// ] -// -// ret += addonSources(ofRoot) -// -// return ret -//} -// -//def srcExcludes(ofRoot){ -// return addonSourcesExclude(ofRoot) -//} -// -//def srcIncludes(ofRoot){ -// return [] -//} -// -// -// -//def addonLdLibs(abi, ofRoot){ -// return [] -//} -// -//def addonLdCompilerFlags(abi, ofRoot){ -// return [] -//} -// -// -//// def getPrebuiltLibPaths(abi, ofRoot) { -//// def libs = ofRoot + 'libs' -// -//// def paths = [] -//// paths += file(libs+"/FreeImage/lib/android/${abi}/libfreeimage.a").toString() -//// paths += file(libs+"/boost/lib/android/${abi}/libboost_filesystem.a").toString() -//// paths += file(libs+"/boost/lib/android/${abi}/libboost_system.a").toString() -//// paths += file(libs+"/freetype/lib/android/${abi}/libfreetype.a").toString() -//// paths += file(libs+"/tess2/lib/android/${abi}/libtess2.a").toString() -//// paths += file(libs+"/curl/lib/android/${abi}/libcurl.a").toString() -//// paths += file(libs+"/openssl/lib/android/${abi}/libssl.a").toString() -//// paths += file(libs+"/openssl/lib/android/${abi}/libcrypto.a").toString() -//// paths += file(libs+"/pugixml/lib/android/${abi}/libpugixml.a").toString() -//// paths += file(libs+"/uriparser/lib/android/${abi}").toString() -//// return paths -//// } -// -// -//def coreLdFlags(abi, ofRoot){ -// def ret = [ -// '-Wl,--exclude-libs,ALL', -// '-Wl,--as-needed', -// '-Wl,--gc-sections' -// ] -// -// def prebuilt = getPrebuiltLibPaths(abi, ofRoot) -// ret.addAll(prebuilt) -// -// return ret -//} -// -// -//def compilerStl(){ -// return "c++_static" -//} -// -// -//// Export the functions -//ext { -// ofAppModuleName = this.&ofAppModuleName -// -// getFlavorName = this.&getFlavorName -// buildToolchain= this.&buildToolchain -// getAbis = this.&getAbis -// compilerStl= this.&compilerStl -// -// appSrcDirs = this.&appSrcDirs -// srcExcludes = this.&srcExcludes -// srcIncludes = this.&srcIncludes -// -// coreCppFlags = this.&coreCppFlags -// addonCppFlags = this.&addonCppFlags -// -// coreLdLibs= this.&coreLdLibs -// addonLdLibs= this.&addonLdLibs -// -// coreLdFlags = this.&coreLdFlags -// addonLdFlags = this.&addonLdFlags -// -// addonData = this.&addonData -// -// addonJavaDependencies = this.&addonJavaDependencies -// javaDependencies = this.&javaDependencies -// -// -//} diff --git a/scripts/dev/create_package.sh b/scripts/dev/create_package.sh index 9936dc86765..ce5ed162a50 100755 --- a/scripts/dev/create_package.sh +++ b/scripts/dev/create_package.sh @@ -485,11 +485,13 @@ function createPackage { # linux remove other platform projects from PG source and copy ofxGui if [ "$PKG_PLATFORM" = "linux" ] || [ "$PKG_PLATFORM" = "linux64" ] || [ "$PKG_PLATFORM" = "linuxarmv6l" ] || [ "$PKG_PLATFORM" = "linuxaarch64" ] || [ "$PKG_PLATFORM" = "linuxarmv7l" ] || [ "$PKG_PLATFORM" = "android" ]; then cd ${PKG_OFROOT} - mv apps/projectGenerator/commandLine . - rm -rf apps/projectGenerator - mkdir apps/projectGenerator - mv commandLine apps/projectGenerator/ - cd apps/projectGenerator/commandLine + if [ -e apps/projectGenerator/commandLine ]; then + mv apps/projectGenerator/commandLine . + rm -rf apps/projectGenerator + mkdir apps/projectGenerator + mv commandLine apps/projectGenerator/ + cd apps/projectGenerator/commandLine + fi deleteCodeblocks deleteVS deleteXcode @@ -651,7 +653,7 @@ function createPackage { fi #create compressed package - if [[ "$PKG_PLATFORM" =~ ^(linux|linux64|android|linuxarmv6l|linuxarmv7l|linuxaarch64|macos|ios|osx)$ ]]; then + if [[ "$PKG_PLATFORM" =~ ^(linux|linux64|android|linuxarmv6l|linuxarmv7l|linuxaarch64|macos|ios|osx)$ ]] && [ "${LIBS_ABI}" != "windows" ]; then if [ "$LIBS_ABI" = "" ]; then PKG_NAME=of_v${PKG_VERSION}_${PKG_PLATFORM}_release else diff --git a/scripts/templates/android2024/ofApp/build.gradle b/scripts/templates/android2024/ofApp/build.gradle index ea57ef37d53..05152c7614e 100644 --- a/scripts/templates/android2024/ofApp/build.gradle +++ b/scripts/templates/android2024/ofApp/build.gradle @@ -1,12 +1,12 @@ plugins { - id 'com.android.application' + id 'com.android.application' } def CMAKELIST_PATH = './src/main/cpp' def CPP_SOURCE = './src/main/cpp' def JAVA_SOURCE = './src/main/java' def PRJ_SRC_ROOT = './src/main' -static def ofRoot(){ return '../../../../' } +def ofRoot(){ return '../../../../' } final ofSource = ofRoot() + 'libs/openFrameworks' final ofLibs = ofRoot() + 'libs' final addons = ofRoot() + 'addons' @@ -17,85 +17,133 @@ def enableProguardInReleaseBuilds = true def enableProguardInDebugBuilds = false task wrapper(type: Wrapper) { - gradleVersion = '8.9.0' + gradleVersion = '8.9.0' } tasks.register("prepareKotlinBuildScriptModel"){ } +def projectRoot = rootProject.projectDir.absolutePath +def addonFile = new File(projectRoot, "addons.make") + +// Get all addon paths from addons.make +def addonPaths = [] +if (addonFile.exists()) { + addonFile.eachLine { line -> + def addonPath = ofRoot + "addons/" + line + if (new File(addonPath).exists()) { + addonPaths.add(addonPath) + } + } +} + +def addonIncludeDirs = [] +def addonLibs = [] + +// Collect include directories and libraries for each addon +addonPaths.each { addon -> + def includePath = new File(addon, "src") + if (includePath.exists()) { + addonIncludeDirs.add(includePath.absolutePath) + } +} + +// Define supported Android ABIs +def supportedAbis = ["arm64-v8a", "armeabi-v7a", "x86_64"] + +addonPaths.each { addon -> + supportedAbis.each { abi -> + def libPath = new File(addon, "libs/android/${abi}") + if (libPath.exists()) { + def libFiles = libPath.listFiles()?.findAll { it.name.endsWith(".so") || it.name.endsWith(".a") } + if (libFiles) { + addonLibs.addAll(libFiles*.absolutePath) + } + } + } +} +println "Addon Libraries found: ${addonLibs}" + +// Convert lists to CMake arguments +def cmakeIncludeArgs = "-DADDON_INCLUDE_DIRS=" + addonIncludeDirs.join(";") +def cmakeLibArgs = "-DADDON_LIBS=" + addonLibs.join(";") + +println "Found addons: " + addonPaths +println "Include directories: " + addonIncludeDirs +println "Libraries: " + addonLibs + evaluationDependsOn(':openFrameworksProject') tasks.whenTaskAdded { task -> - if (task.name == 'assemble') { - task.dependsOn(':openFrameworksProject:assemble') - } + if (task.name == 'assemble') { + task.dependsOn(':openFrameworksProject:assemble') + } } android { - compileSdkVersion 34 - buildToolsVersion '35.0.0' - //ndkPath "/Users/x/android-ndk-r21e" // Point to your own NDK if needed - ndkVersion '28.0.13004108' // use android studio side loaded ndk - buildFeatures { - prefab true - } - signingConfigs { - debug { - } - release { - storeFile new File("${System.properties['user.home']}/.android/debug.keystore") - storeType "jks" - keyAlias 'androiddebugkey' + compileSdkVersion 34 + buildToolsVersion '35.0.0' + //ndkPath "/Users/x/android-ndk-r21e" // Point to your own NDK if needed + ndkVersion '28.0.13004108' // use android studio side loaded ndk + buildFeatures { + prefab true + } + signingConfigs { + debug { + } + release { + storeFile new File("${System.properties['user.home']}/.android/debug.keystore") + storeType "jks" + keyAlias 'androiddebugkey' // storePassword 'android' // <- UPDATE THIS // keyPassword 'android' // <- UPDATE THIS - } - } - defaultConfig { - applicationId "cc.openframeworks.emptyExample" // IMPORTANT : THIS DEFINES THE ID OF THE APK - minSdkVersion 24 - targetSdkVersion 34 - versionCode 12 - versionName '12.0' - ndk.abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64' - - externalNativeBuild { - if (!project.hasProperty("ndkBuild")) { - cmake { - arguments "-DANDROID_STL=c++_shared", - "-DANDROID_ARM_NEON=TRUE", - "-DANDROID_TOOLCHAIN=clang", - //"${OF_ADDONS_ARGUMENTS}", - "-DTARGET_OPENGLES=TRUE" - - version '3.22.1' - } - } - } - multiDexEnabled false - } - buildTypes { - release { - signingConfig signingConfigs.release - jniDebuggable false - debuggable false - minifyEnabled false - shrinkResources false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - signingConfig signingConfigs.release - } - debug { - jniDebuggable true - debuggable true - minifyEnabled false - shrinkResources false - signingConfig signingConfigs.debug - } - } - flavorDimensions "version" - productFlavors { - playstore { - applicationIdSuffix "" - signingConfig signingConfigs.release - } + } + } + defaultConfig { + applicationId "cc.openframeworks.emptyExample" // IMPORTANT : THIS DEFINES THE ID OF THE APK + minSdkVersion 24 + targetSdkVersion 34 + versionCode 12 + versionName '12.0' + ndk.abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64' + + externalNativeBuild { + cmake { + arguments "-DANDROID_STL=c++_shared", + "-DANDROID_ARM_NEON=TRUE", + "-DANDROID_TOOLCHAIN=clang", + cmakeIncludeArgs, // Include paths + cmakeLibArgs // Library paths + "-DTARGET_OPENGLES=TRUE" + + version '3.22.1' + } + } + multiDexEnabled false + } + buildTypes { + release { + signingConfig signingConfigs.release + jniDebuggable false + debuggable false + minifyEnabled false + shrinkResources false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.release + } + debug { + jniDebuggable true + debuggable true + minifyEnabled false + shrinkResources false + signingConfig signingConfigs.debug + } + } + flavorDimensions "version" + productFlavors { + playstore { + applicationIdSuffix "" + signingConfig signingConfigs.release + } // humble { // applicationIdSuffix ".humble" // } @@ -108,35 +156,35 @@ android { // oppo { // applicationIdSuffix ".oppo" // } - } - sourceSets { - main { - manifest.srcFile "${PRJ_SRC_ROOT}/AndroidManifest.xml" - java.srcDirs = ["${PRJ_SRC_ROOT}/java", - "${OFX_ANDROID}/Java"] - res.srcDirs = ["${PRJ_SRC_ROOT}/res"] - assets { - srcDirs 'src/main/assets', 'src/main/bin/data' - } - } - } - externalNativeBuild { + } + sourceSets { + main { + manifest.srcFile "${PRJ_SRC_ROOT}/AndroidManifest.xml" + java.srcDirs = ["${PRJ_SRC_ROOT}/java", + "${OFX_ANDROID}/Java"] + res.srcDirs = ["${PRJ_SRC_ROOT}/res"] + assets { + srcDirs 'src/main/assets', 'src/main/bin/data' + } + } + } + externalNativeBuild { cmake { path "${CMAKELIST_PATH}/CMakeLists.txt" } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - androidResources { - noCompress '' - } - dependenciesInfo { - includeInApk false - includeInBundle false - } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + androidResources { + noCompress '' + } + dependenciesInfo { + includeInApk false + includeInBundle false + } namespace 'cc.openframeworks.android' // testOptions { // devices { @@ -156,19 +204,19 @@ android { dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'androidx.appcompat:appcompat:1.7.0' - implementation 'androidx.constraintlayout:constraintlayout:2.2.1' - implementation 'androidx.legacy:legacy-support-v4:1.0.0' - implementation "com.getkeepsafe.relinker:relinker:1.4.5" - implementation 'com.google.android.material:material:1.12.0' - if (project.hasProperty("googleplay")) { - implementation "com.google.android.gms:play-services-games:22.0.1" - implementation "com.google.android.gms:play-services-auth:20.0.1" - implementation "com.google.android.gms:play-services-base:18.0.1" - implementation "com.google.android.gms:play-services-basement:18.0.0" - implementation "com.google.android.gms:play-services-instantapps:18.0.1" - implementation "com.google.android.gms:play-services-appset:16.0.2" - } + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.appcompat:appcompat:1.7.0' + implementation 'androidx.constraintlayout:constraintlayout:2.2.1' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation "com.getkeepsafe.relinker:relinker:1.4.5" + implementation 'com.google.android.material:material:1.12.0' + if (project.hasProperty("googleplay")) { + implementation "com.google.android.gms:play-services-games:22.0.1" + implementation "com.google.android.gms:play-services-auth:20.0.1" + implementation "com.google.android.gms:play-services-base:18.0.1" + implementation "com.google.android.gms:play-services-basement:18.0.0" + implementation "com.google.android.gms:play-services-instantapps:18.0.1" + implementation "com.google.android.gms:play-services-appset:16.0.2" + } } diff --git a/scripts/templates/android2024/ofApp/src/main/cpp/CMakeLists.txt b/scripts/templates/android2024/ofApp/src/main/cpp/CMakeLists.txt index 6ecc1184538..9d915f7a17c 100644 --- a/scripts/templates/android2024/ofApp/src/main/cpp/CMakeLists.txt +++ b/scripts/templates/android2024/ofApp/src/main/cpp/CMakeLists.txt @@ -2,6 +2,7 @@ # library. cmake_minimum_required(VERSION 3.22.1) +# important the projectName is ofApp to be linked - see relinker project(ofApp LANGUAGES CXX) set(TARGET_ANDROID TRUE) @@ -59,7 +60,7 @@ elseif(OF_LIBRARY_TYPE STREQUAL "STATIC") set(LIB_EXTENSION ".a") endif() -add_library( ofApp +add_library( ${PROJECT_NAME} ${OF_LIBRARY_TYPE} # src files for project (just c/cpp) ${CMAKE_SOURCE_DIR}/main.cpp @@ -107,20 +108,33 @@ include_directories( ${OF_ANDROID} ) +# Load add-on include directories from Gradle +if(DEFINED ADDON_INCLUDE_DIRS) + foreach(DIR ${ADDON_INCLUDE_DIRS}) + include_directories(${DIR}) + endforeach() +endif() +if(DEFINED ADDON_LIBS) + message(STATUS "Adding addon libraries: ${ADDON_LIBS}") + foreach(LIB ${ADDON_LIBS}) + target_link_libraries(${PROJECT_NAME} ${LIB}) + endforeach() +endif() + find_library(ANDROID_LIB NAMES android) find_library(LOG_LIB NAMES log) find_library(GLES1_LIB NAMES GLESv1_CM) find_library(GLES2_LIB NAMES GLESv2) find_library(GLES3_LIB NAMES GLESv3) -target_link_libraries(ofApp +target_link_libraries(${PROJECT_NAME} android log m z dl ) -target_link_libraries(ofApp +target_link_libraries(${PROJECT_NAME} ${ANDROID_LIB} ${GLES2_LIB} ${GLES3_LIB} @@ -128,5 +142,5 @@ target_link_libraries(ofApp ${LOG_LIB} ) -target_link_libraries( ofApp +target_link_libraries( ${PROJECT_NAME} ${OF_ANDROID_OUTPUT}/${ANDROID_ABI}/libopenFrameworksAndroid${LIB_EXTENSION})