Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS: Failure to build with --configuration Release #49

Closed
Drew-Gerber opened this issue Jan 4, 2023 · 14 comments
Closed

iOS: Failure to build with --configuration Release #49

Drew-Gerber opened this issue Jan 4, 2023 · 14 comments
Labels
investigating Ongoing conversation about the issue question Questions, sometimes needing docs SDK 47 Affects plugin in Expo SDK 47

Comments

@Drew-Gerber
Copy link

Hello!

I'm trying to use expo-community-flipper in combination with Expo prebuild/run:ios and seeing the below error when running expo run:ios --configuration Release - simply running expo run:ios (aka Debug configuration) works fine and the Flipper integration works great 💯.

I tried using FLIPPER_DISABLE=1 but was seeing the same error. I also tried a expo prebuild -p ios --clean after installing expo-community-flipper.

The error

❌  Undefined symbols for architecture x86_64
┌─ Symbol: _OBJC_CLASS_$_FlipperClient
└─ Referenced from: objc-class-ref in libreact-native-flipper.a(FlipperReactNativeJavaScriptPluginManager.o)


❌  ld: symbol(s) not found for architecture x86_64



❌  clang: error: linker command failed with exit code 1 (use -v to see invocation)


› Linking   tempexposandbox » tempexposandbox
❌  Undefined symbols for architecture arm64
┌─ Symbol: _OBJC_CLASS_$_FlipperClient
└─ Referenced from: objc-class-ref in libreact-native-flipper.a(FlipperReactNativeJavaScriptPluginManager.o)


❌  ld: symbol(s) not found for architecture arm64



❌  clang: error: linker command failed with exit code 1 (use -v to see invocation)


    Run script build phase 'Start Packager' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'tempexposandbox' from project 'tempexposandbox')
    Run script build phase 'Bundle React Native code and images' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'tempexposandbox' from project 'tempexposandbox')
    Run script build phase '[CP-User] Generate app.config for prebuilt Constants.manifest' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'EXConstants' from project 'Pods')

› 6 error(s), and 3 warning(s)

CommandError: Failed to build iOS project. "xcodebuild" exited with error code 65.

Here's my app.config.js file:

const config = {
  expo: {
    name: "temp-expo-sandbox",
    slug: "temp-expo-sandbox",
    version: "1.0.0",
    orientation: "portrait",
    icon: "./assets/images/icon.png",
    scheme: "myapp",
    jsEngine: "hermes",
    userInterfaceStyle: "automatic",
    splash: {
      image: "./assets/images/splash.png",
      resizeMode: "contain",
      backgroundColor: "#ffffff",
    },
    plugins: ["expo-community-flipper"],
    updates: {
      fallbackToCacheTimeout: 0,
    },
    assetBundlePatterns: ["**/*"],
    ios: {
      supportsTablet: true,
      bundleIdentifier: "XXXXX",
    },
    android: {
      adaptiveIcon: {
        foregroundImage: "./assets/images/adaptive-icon.png",
        backgroundColor: "#ffffff",
      },
      package: "XXXXX",
    },
    web: {
      favicon: "./assets/images/favicon.png",
    },
  },
};

module.exports = config;

And finally, here's my package.json dependencies:

  "dependencies": {
    "@expo/vector-icons": "^13.0.0",
    "@react-navigation/bottom-tabs": "^6.0.5",
    "@react-navigation/native": "^6.0.2",
    "@react-navigation/native-stack": "^6.1.0",
    "expo": "~47.0.9",
    "expo-asset": "~8.6.2",
    "expo-community-flipper": "^47.0.0",
    "expo-constants": "~14.0.2",
    "expo-dev-client": "~2.0.1",
    "expo-font": "~11.0.1",
    "expo-linking": "~3.2.3",
    "expo-splash-screen": "~0.17.5",
    "expo-status-bar": "~1.4.2",
    "expo-system-ui": "~2.0.1",
    "expo-web-browser": "~12.0.0",
    "react": "18.1.0",
    "react-dom": "18.1.0",
    "react-native": "0.70.5",
    "react-native-flipper": "0.175.0",
    "react-native-safe-area-context": "4.4.1",
    "react-native-screens": "~3.18.0",
    "react-native-web": "~0.18.9"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@types/react": "~18.0.24",
    "@types/react-native": "~0.70.6",
    "jest": "^26.6.3",
    "jest-expo": "~47.0.1",
    "react-test-renderer": "18.1.0",
    "typescript": "^4.6.3"
  },

Thank you for all the hard work you do on this plugin 🙏

@jakobo
Copy link
Owner

jakobo commented Jan 6, 2023

Since you're including react-native-flipper in your package.json, you'll also need to specify the rnf version in the config plugin.

// app.config.js
{
  "expo": {
    "..."
    "plugins": [
      ["expo-community-flipper", "0.175.0"]
    ]
  }
}

0.175.0 is verified as working over here so it might just be a config issue as part of the setup.

@jakobo jakobo added investigating Ongoing conversation about the issue question Questions, sometimes needing docs SDK 47 Affects plugin in Expo SDK 47 labels Jan 6, 2023
@Nantris
Copy link

Nantris commented Jan 17, 2023

FlipperOptions, as the readme calls it, didn't used to be necessary to build the app successfully. I wonder what changed. In any event, it may call for some update to the readme since our otherwise working project suddenly stopped building on iOS.

I'm testing that solution now, but 8 hours in EAS build queue until I can report back.

@jakobo
Copy link
Owner

jakobo commented Jan 17, 2023

The FlipperOptions should still be optional, even in 47.* and may represent a bug. @slapbox, are you getting a TS error, one of the plugin's errors asking for the podfile to be submitted as a bug, or an error from EAS during build?

Asking because the FlipperOptions last changed during SDK 46. However, if you include a version of react-native-flipper in package.json with a version that differs from the pod bundled with react-native, things will go awry. In that scenario, the cocoapod dependency system cannot disambiguate which flipper to use, resulting in a variety of build errors.

With react-native including a flipper version by default, this might become more of an issue and be worth including in the readme.

@Nantris
Copy link

Nantris commented Jan 18, 2023

I think the key here is that 0.175.0 or below are necessary - I guess maybe because that's the latest version compatible with what's bundled with react-native?

In that case, I don't think we need to specify the version - but since EAS isn't even accepting new builds and I'm still 4 hours away from mine starting, I can't report back until tomorrow (a wildly optimistic projection.)

The error wasn't TypeScript, it was the below:

image

@jakobo
Copy link
Owner

jakobo commented Jan 18, 2023

I guess maybe because that's the latest version compatible with what's bundled with react-native

💯 likely the cause. This is because Flipper's on 0.x.y, meaning any x can include breaking changes to pieces of AppDelegate or other parts of the ios code Expo abstracts away for us.

The only time you really need to specify the version is when you need JS plugin functionality (such as the redux inspector) inside of Flipper. If all you need is layout & debugging, you can just use plugin w/o a version (and no react-native-flipper in package.json) and it should work using the RN defaults.

@PimButton
Copy link

I'm having the same issue. We are using JS plugin functionality (react-query-native-devtools) so we need to have react-native-flipper inside package.json.
Like @Drew-Gerber describes, a Development build builds with no problem. As soon as we try to build a Preview build, EAS fails with the same error as @slapbox has shown.
I have tried with and without including the RNF version in the config plugin as suggested by @jakobo but this makes no difference.

Relevant parts of our setup:
package.json:

  "dependencies": {
    "....",
    "expo-community-flipper": "^47.0.0",
    "react-native": "0.70.5",
    "react-native-flipper": "^0.175.0",
    "react-query-native-devtools": "^4.0.0",
  },

app.config.js

{
  "expo": {
    "..."
    "plugins": [
      [
        "expo-notifications",
        {
          "icon": "./assets/adaptive-icon.png",
          "color": "#EFF5FC"
        }
      ],
      ["expo-community-flipper", "0.175.0"]
    ]
  }
}

eas.json

{
  "cli": {
    "version": ">= 2.6.0"
  },
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal",
      "android": {
        "buildType": "apk"
      },
      "ios": {
        "simulator": true,
        "resourceClass": "m1-medium"
      },
      "channel": "development"
    },
    "preview": {
      "distribution": "internal",
      "channel": "preview",
      "ios": {
        "resourceClass": "m1-medium"
      }
    },
    "production": {
      "channel": "production"
    }
  },
  "submit": {
    "production": {}
  }
}

Error in EAS:
Screenshot 2023-01-20 at 11 20 04

@jakobo
Copy link
Owner

jakobo commented Jan 24, 2023

Just documenting some discoveries:

The good news is, we can test this fix locally. Here's a stripped down JS version of the plugin, specifically for iOS. I'll see about adding this with tests in the meantime.

// flipper.js
// install locally @expo/config-plugins, expo
// use this instead of the community plugin for testing
import path from "path";
import fs from "fs";
import { withDangerousMod } from "expo/config-plugins";
import {
  mergeContents,
  removeContents,
} from "@expo/config-plugins/build/utils/generateCode";

// set flipper here or `false` for default version
const FLIPPER_VERSION = "0.163.0";

/** In iOS, this is the line we anchor to for adding args to use_react_native!() */
export const IOS_URN_ARG_ANCHOR =
  /:fabric_enabled => flags\[:fabric_enabled\],/;

/** In a Podfile, this regex tells us the :production arg is already there */
export const IOS_HAS_PRODUCTION_ARG =
  /use_react_native!\([\s\S]*:production\s+=>/gm;

/** In a Podfile, this regex tells us the :flipper_configuration arg is already there */
export const IOS_HAS_FLIPPER_ARG =
  /use_react_native!\([\s\S]*^\s*:flipper_configuration\s+=>/gm;

// make a flipper arg
const createFlipperArgument = () => {
  const active = FLIPPER_VERSION 
    ? `FlipperConfiguration.enabled(["Debug", "Dev.Debug", "Release"], { 'Flipper' => '${FLIPPER_VERSION }' }),`
    : `FlipperConfiguration.enabled(["Debug", "Dev.Debug", "Release"]),`;
  return `:flipper_configuration => ${active}`;
};

// strips tagged content
const removeTaggedContent = (contents, ns) => {
  return removeContents({ src: contents, tag: tag(ns) });
};

// get last mutation result
const last = (arr) => {
  const l = arr[arr.length - 1];
  if (typeof l === "undefined") {
    throw new Error(
      "No prior results. This is a bug in expo-community-flipper and should be reported"
    );
  }
  return l;
};

// edit podfile step
export function updatePodfileContentsWithFlipper(
  contents
) {
  const results = [];
  results.push(removeTaggedContent(contents, "urn"));

  const preexisting = IOS_HAS_FLIPPER_ARG.test(last(results).contents);

  if (!preexisting) {
    results.push(
      mergeContents({
        tag: tag("urn"),
        src: last(results).contents,
        newSrc: createFlipperArgument(),
        anchor: IOS_URN_ARG_ANCHOR,
        offset: 1,
        comment: "#",
      })
    );
  }

  if (!last(results).didMerge) {
    throw new Error(
      "Cannot add flipper arguments to the project's ios/Podfile. Please report this with a copy of your project Podfile. You can generate this with the `expo prebuild` command."
    );
  }
  return last(results).contents;
}

// update podfile mod
function withFlipperPodfile(config) {
  config = withDangerousMod(config, [
    "ios",
    async (c) => {
      const filePath = path.join(c.modRequest.platformProjectRoot, "Podfile");
      const contents = fs.readFileSync(filePath, "utf-8");
      const updatedContents = updatePodfileContentsWithFlipper(contents, cfg);
      fs.writeFileSync(filePath, updatedContents);
      return c;
    },
  ]);

  return config;
}

// plugin entry point
export default function withFlipperIOS(config) {
  config = withFlipperPodfile(config);
  return config;
}
// app.config.js
module.exports = {
  "expo": {
    "..."
    "plugins": [
      "./path/to/flipper.js"
    ]
}

@jakobo
Copy link
Owner

jakobo commented Jan 24, 2023

I've just pushed v 47.0.1 which is backward compatible with 47.0.0 and should address the most likely culprits:

  • We enable the Release profile, along with Debug and Dev.Debug based on the linked flipper thread. It's very likely that building with the metro Release configuration is creating a scenario where the react-native scripts want to add Flipper but the pod was never included in the build. Shifting the enable/disable to our app.config.js is a more expo-like way of approaching it
  • 47.0.1 also includes a "hard-disable" of setting the env value NO_FLIPPER to 1. This explicitly passes FlipperConfiguration.disabled which should prevent all podfile linking from happening. Going forward, this will also let us identify upstream issues easier.

@jakobo
Copy link
Owner

jakobo commented Jan 24, 2023

@all-contributors
please add @Drew-Gerber for bugs.
please add @PimButton for bugs.

@jacob3794
Copy link

With the Dev.Debug profile added after running yarn ios I'm currently getting the following error on SDK 47

⚠️  Something went wrong running `pod install` in the `ios` directory.
Command `pod install` failed.
└─ Cause: Unknown configuration whitelisted: dev.debug. CocoaPods found debug and release, did you mean one of these?

This is my Podfile, and removing Dev.Debug seems to resolve the issue.

require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
require File.join(File.dirname(`node --print "require.resolve('@react-native-community/cli-platform-ios/package.json')"`), "native_modules")

require 'json'
podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {}

platform :ios, podfile_properties['ios.deploymentTarget'] || '13.0'
install! 'cocoapods',
  :deterministic_uuids => false

target 'IOSApp' do
  use_expo_modules!
  config = use_native_modules!

  use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']

  # Flags change depending on the env values.
  flags = get_default_flags()

  use_react_native!(
    :path => config[:reactNativePath],
# @generated begin expo-community-flipper-isprod - expo prebuild (DO NOT MODIFY) sync-828c22a1a38236bf5b7c203393f474bc68356b34
    # ENV value added to support Hermes
    :production => ENV["PRODUCTION"] == "1" ? true : false,
# @generated end expo-community-flipper-isprod
    :hermes_enabled => podfile_properties['expo.jsEngine'] == 'hermes',
    :fabric_enabled => flags[:fabric_enabled],
# @generated begin expo-community-flipper-urn - expo prebuild (DO NOT MODIFY) sync-b49de04cb8d73b4529a5f4b5f77c50dc458ee8ce
    :flipper_configuration => FlipperConfiguration.enabled(["Debug", "Dev.Debug", "Release"]),
# @generated end expo-community-flipper-urn
    # An absolute path to your application root.
    :app_path => "#{Pod::Config.instance.installation_root}/..",
    #
    # Uncomment to opt-in to using Flipper
    # Note that if you have use_frameworks! enabled, Flipper will not work
    # :flipper_configuration => !ENV['CI'] ? FlipperConfiguration.enabled : FlipperConfiguration.disabled,
  )

  post_install do |installer|
    react_native_post_install(
      installer,
      # Set `mac_catalyst_enabled` to `true` in order to apply patches
      # necessary for Mac Catalyst builds
      :mac_catalyst_enabled => false
    )
    __apply_Xcode_12_5_M1_post_install_workaround(installer)

    # This is necessary for Xcode 14, because it signs resource bundles by default
    # when building for devices.
    installer.target_installation_results.pod_target_installation_results
      .each do |pod_name, target_installation_result|
      target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
        resource_bundle_target.build_configurations.each do |config|
          config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
        end
      end
    end
  end

  post_integrate do |installer|
    begin
      expo_patch_react_imports!(installer)
    rescue => e
      Pod::UI.warn e
    end
  end
end

@jakobo
Copy link
Owner

jakobo commented Jan 25, 2023

With the Dev.Debug profile added after running yarn ios I'm currently getting the following error on SDK 47

I'll get a fix out today with only debug & release profiles for metro. I don't think we need to configure the profiles, but I'm surprised there's a whitelist now

@jakobo
Copy link
Owner

jakobo commented Jan 26, 2023

Update: 47.0.2 is out with only the Debug and Release configurations enabled. That should get everyone to a working state. LMK if more EAS issues come up. Thank you @jacob3794 for doing a build test w/ the Dev.Debug configuration removed.

@PimButton
Copy link

I can confirm that 47.0.2 fixes the issue and a Release build is created with no problem!
@jacob3794 thanks for the great work!

@jakobo jakobo closed this as completed Feb 3, 2023
@luispuig
Copy link

I am having the same issue, still with version 47.0.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
investigating Ongoing conversation about the issue question Questions, sometimes needing docs SDK 47 Affects plugin in Expo SDK 47
Projects
None yet
Development

No branches or pull requests

6 participants