expo / config-plugins

Out-of-tree Expo config plugins for packages that haven't adopted the config plugin system yet.
445 stars 95 forks source link

Android build error for ffmpeg-kit-react-native #31

Closed charles-goode closed 1 year ago

charles-goode commented 2 years ago

While building a dev client for android (on EAS) the gradle step fails with

[stderr] FAILURE: Build failed with an exception.
[stderr] * What went wrong:
[stderr] Execution failed for task ':app:mergeDebugNativeLibs'.
[stderr] > A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
[stderr]    > More than one file was found with OS independent path 'lib/x86/libc++_shared.so'.
 If you are using jniLibs and CMake IMPORTED targets, 
see https://developer.android.com/studio/preview/features#automatic_packaging_of_prebuilt_dependencies_used_by_cmake

Which I've seen before and fixed for myself with a patch-package while integrating react-native-mmkv in my managed expo app. I found mention of this issue on the old version of ffmpeg-kit-react-native which was react-native-ffmpeg. The fix made it into the Tips for the new repo. I believe this is a necessary step for the config plugin to work properly for android and the other ffmpeg binaries (I'm trying to use full-gpl). In the meantime, I'll try to write a patch for the plugin that incorporates this fix. Btw thanks Evan for the plugin. It works great on iOS and was essential for supporting cross-platform video sharing in my expo app.

charles-goode commented 2 years ago

This patch-package fixed the error. It isn't very robust though as it assumes the app build.gradle didn't already have android.packagingOptions defined. Just figured I'd share so others can work off of it.

diff --git a/node_modules/@config-plugins/ffmpeg-kit-react-native/build/withAndroidFFMPEGPackage.js b/node_modules/@config-plugins/ffmpeg-kit-react-native/build/withAndroidFFMPEGPackage.js
index 700b122..5f1b76f 100644
--- a/node_modules/@config-plugins/ffmpeg-kit-react-native/build/withAndroidFFMPEGPackage.js
+++ b/node_modules/@config-plugins/ffmpeg-kit-react-native/build/withAndroidFFMPEGPackage.js
@@ -27,6 +27,27 @@ function addPackageName(src, packageName) {
         comment: "//",
     }).contents;
 }
+const withAndroidSharedLibraryHandled = (config) => {
+    return config_plugins_1.withAppBuildGradle(config, (config) => {
+        if (config.modResults.language === "groovy") {
+            const fileStr = config.modResults.contents;
+            // const searchForExistingPackagingOptions = new RegExp(`(packagingOptions \{ )`)
+            // if no existing packagingOptions let's put it at the top of the android build.gradle
+            const regex = new RegExp('(android \{)')
+            config.modResults.contents = fileStr.replace(regex, `$1\n\tpackagingOptions {
+        pickFirst 'lib/x86/libc++_shared.so'
+        pickFirst 'lib/x86_64/libc++_shared.so'
+        pickFirst 'lib/armeabi-v7a/libc++_shared.so'
+        pickFirst 'lib/arm64-v8a/libc++_shared.so'
+    }\n` );
+        }
+        else {
+            throw new Error("Cannot add camera maven gradle because the build.gradle is not groovy");
+        }
+        return config;
+    });
+}
+exports.withAndroidSharedLibraryHandled = withAndroidSharedLibraryHandled;
 exports.addPackageName = addPackageName;
 // Fork of config-plugins mergeContents, but appends the contents to the end of the file.
 function appendContents({ src, newSrc, tag, comment, }) {
diff --git a/node_modules/@config-plugins/ffmpeg-kit-react-native/build/withFFMPEG.js b/node_modules/@config-plugins/ffmpeg-kit-react-native/build/withFFMPEG.js
index 9509ebe..0499cdc 100644
--- a/node_modules/@config-plugins/ffmpeg-kit-react-native/build/withFFMPEG.js
+++ b/node_modules/@config-plugins/ffmpeg-kit-react-native/build/withFFMPEG.js
@@ -38,6 +38,7 @@ const withFFMPEG = (config, _props) => {
             },
         ],
         [withAndroidFFMPEGPackage_1.withAndroidFFMPEGPackage, androidPackage],
+        withAndroidFFMPEGPackage_1.withAndroidSharedLibraryHandled,
     ]);
 };
 module.exports = config_plugins_1.createRunOncePlugin(withFFMPEG, pkg.name, pkg.version);
EvanBacon commented 2 years ago

So we need to add the following android.packagingOptions?:

pickFirst 'lib/x86/libc++_shared.so'
pickFirst 'lib/x86_64/libc++_shared.so'
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
pickFirst 'lib/arm64-v8a/libc++_shared.so'
EvanBacon commented 2 years ago

Something I'm thinking about doing is adding the following block to the android/app/build.gradle in the template:


// Apply static values from `gradle.properties` to the `android.packagingOptions`
// Accepts values in comma delimited lists, example:
// android.packagingOptions.pickFirsts=/LICENSE,**/picasa.ini
["pickFirsts", "excludes", "merges", "doNotStrip"].each { packagingOptionName ->
    // Split option: 'foo,bar' -> ['foo', 'bar']
    // `[] - ""` is essentially `[""].filter(Boolean)` removing all empty strings.
    def options = (findProperty("android.packagingOptions.$packagingOptionName") ?: "").split(",") - "";
    if (options.length > 0) {
        println "android.packagingOptions.$packagingOptionName += $options $options.length"
        // Ex: android.packagingOptions.pickFirsts += '**/SCCS/**'
        options.each {
            android.packagingOptions[packagingOptionName] += it
        }
    }
}

Then we can add values safely to the gradle.properties. In the short term, from my research, it appears that we could regex in the following sometime after the android {}

android.packagingOptions.pickFirsts += ['lib/x86/libc++_shared.so', 'lib/x86_64/libc++_shared.so', 'lib/armeabi-v7a/libc++_shared.so', 'lib/arm64-v8a/libc++_shared.so']

This would prevent defaults and ensure that we don't overwrite the existing object.

hirbod commented 2 years ago

Some people also do report issue with lib/x86/libhermes.so. Beside of the 4 you already defined, these are all the shared libs I've encountered so far.

lachenmayer commented 1 year ago

We have also been encountering this issue. Now that https://github.com/expo/expo/pull/15863 is merged, this is a pretty straightforward fix - I have implemented this in https://github.com/expo/config-plugins/pull/159.