lugg / react-native-config

Bring some 12 factor love to your mobile apps!
MIT License
4.82k stars 657 forks source link

'GeneratedDotEnv.m' file not found #187

Closed thedevdavid closed 4 years ago

thedevdavid commented 6 years ago

If I use this package with Cocoapods and follow the README's instructions, the iOS build fails every time. With C Preprocessor error "'GeneratedDotEnv.m' file not found".

Without any pods, it works.

Does anybody have any experience with this? I'm stuck for 2 days now because of this issue. I can't find any solution. I tried a lot of things by now.

selfeky commented 6 years ago

@DLevai94 I have the same issue. Did you find a solution?

aestrro commented 6 years ago

I am running into the same issue, this error seems to be happening on react-native 0.50.+

Can the following commit be problematic for react-native link react-native-config? https://github.com/facebook/react-native/commit/4c196aec902fa0b9187e11f964aed0941778a2ae

thedevdavid commented 6 years ago

@selfeky unfortunately no.

Is it possible that react-native-firebase package has the same issue? https://github.com/facebook/react-native/pull/15460#issuecomment-346295149

aestrro commented 6 years ago

Yeah, reading up on it it seems the community who uses it excitedly wanted to jump on the 50.x version of RN. Folks, this is a beautiful project - I'll write more tests on my backend while this is in flight. Great job, it has reduced plenty of my RN complications my life in many ways. I'll be patient.

birkir commented 6 years ago

I used to have my own version of react-native-config, because the project was stale for a while, but I came up with a solution that works quite well with cocoapods for now.

Add thisbuild-env.sh file somewhere in your project (for example ./scripts/build-env.sh)

#/bin/sh
TARGET_ENV=".env"
RNCDIR="./node_modules/react-native-config/ios"

if [ ! -z "$SYMROOT" ]; then
  # Ensure directories exist before copying files
  mkdir -p $SYMROOT
  mkdir -p $BUILD_DIR

  # Build dotenv
  cd $RNCDIR
  ./ReactNativeConfig/BuildDotenvConfig.ruby
  cd -

  # Copy generated dotenv files to node_modules directory
  cp "$BUILD_DIR/GeneratedInfoPlistDotEnv.h" "$RNCDIR/ReactNativeConfig/GeneratedInfoPlistDotEnv.h"
  cp "$SYMROOT/GeneratedDotEnv.m" "$RNCDIR/ReactNativeConfig/GeneratedDotEnv.m"
fi
  1. (Menu) Editor > Add target
  2. Select Cross-Platform from the top and then "External Build System".
  3. Write build-env as Product Name, update your identifiers etc.
  4. Edit the fields as following:
    • Build Tool: ${SRCROOT}/../scripts/build-env.sh
    • Arguments: $(ACTION)
    • Directory: ${SRCROOT}/..
    • ✅ Pass build settings in environment
  5. (Menu) Product > Scheme > Edit Scheme
  6. Select Build from the left menu.
  7. Press the + symbol from the bottom of the window.
  8. Select build-env from the list.
  9. Move it to the top of list (before your product)
  10. Done!

Now you can use the module as-is with cocoapods. I have a even better solution with dynamically built env for JS, so I don't have to clean and build again while developing (https://github.com/ueno-llc/react-native-starter).

GunnarHolwerda commented 6 years ago

Hi all, I ran into this error and was using @birkir's method for resolving the issue involving CocoaPods. It was working fine util I had to archive my project where BuildDotenvConfig.rb would error on attempting to copy the GeneratedDotEnv.m and GeneratedInfoPlistDotEnv.h files.

To fix this issue I updated BuildDotenvConfig.rb to add all lines with the comment # ADD THIS LINE

#!/usr/bin/env ruby
require 'fileutils' # ADD THIS LINE
# Allow utf-8 charactor in config value
# For example, APP_NAME=中文字符
Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = Encoding::UTF_8

defaultEnvFile = ".env"

# pick a custom env file if set
if File.exists?("/tmp/envfile")
  custom_env = true
  file = File.read("/tmp/envfile").strip
else
  custom_env = false
  file = ENV["ENVFILE"] || defaultEnvFile
end

puts "Reading env from #{file}"

dotenv = begin
  # https://regex101.com/r/cbm5Tp/1
  dotenv_pattern = /^(?:export\s+|)(?<key>[[:alnum:]_]+)=((?<quote>["'])?(?<val>.*?[^\\])\k<quote>?|)$/

  # find that above node_modules/react-native-config/ios/
  path = File.join(Dir.pwd, "../../../#{file}")
  if File.exists?(path)
    raw = File.read(path)
  elsif File.exists?(file)
    raw = File.read(file)    
  else
    defaultEnvPath = File.join(Dir.pwd, "../../../#{defaultEnvFile}")
    if !File.exists?(defaultEnvPath)
      # try as absolute path
      defaultEnvPath = defaultEnvFile
    end
    defaultRaw = File.read(defaultEnvPath)
    if (defaultRaw)
      raw = defaultRaw + "\n" + raw
    end
  end

  raw.split("\n").inject({}) do |h, line|
    m = line.match(dotenv_pattern)
    next h if m.nil?
    key = m[:key]
    # Ensure string (in case of empty value) and escape any quotes present in the value.
    val = m[:val].to_s.gsub('"', '\"')
    h.merge(key => val)
  end
rescue Errno::ENOENT
  puts("**************************")
  puts("*** Missing .env file ****")
  puts("**************************")
  {} # set dotenv as an empty hash
end

# create obj file that sets DOT_ENV as a NSDictionary
dotenv_objc = dotenv.map { |k, v| %Q(@"#{k}":@"#{v}") }.join(",")
template = <<EOF
  #define DOT_ENV @{ #{dotenv_objc} };
EOF

# ensure paths exist
FileUtils.mkdir_p ENV["SYMROOT"] # ADD THIS LINE
FileUtils.mkdir_p ENV["BUILD_DIR"] # ADD THIS LINE

# write it so that ReactNativeConfig.m can return it
path = File.join(ENV["SYMROOT"], "GeneratedDotEnv.m")

File.open(path, "w") { |f| f.puts template }

# create header file with defines for the Info.plist preprocessor
info_plist_defines_objc = dotenv.map { |k, v| %Q(#define __RN_CONFIG_#{k}  #{v}) }.join("\n")

# write it so the Info.plist preprocessor can access it
path = File.join(ENV["BUILD_DIR"], "GeneratedInfoPlistDotEnv.h")
File.open(path, "w") { |f| f.puts info_plist_defines_objc }

if custom_env
  File.delete("/tmp/envfile")
end

puts "Wrote to #{path}"

This ensured the full file paths I was attempting to write to existed before writing.

birkir commented 6 years ago

Yes I ran into this as well at some point on a new project that didn't have any previously archived builds, I updated the shell script snippet.

timothepearce commented 6 years ago

Hi guys, is this the only solution right now to use react-native-config with cocoapods?

ifero commented 6 years ago

Yes, at the moment the only solutions available are @birkir or mine (https://github.com/luggit/react-native-config/issues/83#issuecomment-349974826), but @birkir 's is much more cleaner and work inside Xcode. The only think that I don't like is that I had to create 3 build-env.sh files, one for each target (prod, stage, dev)

alextorn commented 6 years ago

Folks, you should double check if libReactNativeConfig.a is available in target settings - Build Phases - Link Binary With Libraries:

screenshot 2018-02-06 17 12 11

Sometimes regular automatic linking is not enough. I solved the problem by manual linking react-native-config library.

react-native: v 0.52.2 react-native-config: v 0.11.5

UPD: I cleaned cache and found that linking is not enough...

dancomanlive commented 6 years ago

@alextorn libReactNativeConfig.a is missing indeed. Would you be so kind to elaborate on the manual linking? The RN docs are not very clear. Thanks!

apparition47 commented 6 years ago

After spending half a day on this, managed to get get this project to build and expose the .env in JS but without CocoaPods. Instead, I manually linked this project as which I documented in my updated README.

Using RN 0.53.0.

Basically the process is to:

  1. add the ../node_modules/react-native-config/ios/ReactNativeConfig.xcodeproj to your own project
  2. In your Target settings, Build Phases, Link Binary With Libraries, add libReactNativeConfig.a.
  3. Manage scheme, expand "Build", click "Pre-actions", "New Run Script Action", enter:
    if [ "${ENVFILE}" ]; then echo "${ENVFILE}" > /tmp/envfile ; else echo ".env" > /tmp/envfile; fi
  4. Ensure your .env.prod file has some key/values without spaces around the = like I've been seeing around these threads. Then run in term: $ ENVFILE=.env.prod react-native run-ios.
benjaminketron commented 6 years ago

@apparition47 Thank you. This saved a bit of time. In practice i found step three to be unnecessary when importing with

#import <ReactNativeConfig/ReactNativeConfig.h>

rather than

#import "ReactNativeConfig.h"

Does that make sense or did I miss something in the thread you were targeting with step 3?

PatNeedham commented 6 years ago

@birkir I tried following your suggestion with the ./scripts/build-env.sh file and adding it to the new build-env target, but when attempting to build or clean the app from Xcode, I always get Shell Script Invocation Error:

make: *** No targets specified and no makefile found.  Stop.
Command /usr/bin/make failed with exit code 2

Same result even after changing the permissions for that shell script. Did you are anyone else run into this script invocation issue as well, and if so how was it resolved?

timothepearce commented 6 years ago

@PatNeedham It works for me, I remember I got your mistake when I positioned the target after React in the build order.

Try in that one:

capture d ecran 2018-04-26 a 22 41 28

I hope it helps you.

PatNeedham commented 6 years ago

@TimothePearce my targets were also in that order. When I clicked on the Manage Schemes... button in the lower left of that pop-up, I noticed build-env did not initially have Shared checked on the right hand column:

image

Having that checked still produced the same shell script invocation result.

Running ls -l scripts/build-env.sh from command line results in

---------x  1 patneedham  staff  553 Apr 26 15:16 scripts/build-env.sh

Actually made some changes to eliminate those permission restrictions so it is now like this:

-rwxrwxrwx  1 patneedham  staff  553 Apr 26 17:12 scripts/build-env.sh

Same result when trying to run Xcode build. Do those updated permissions look off somehow?

timothepearce commented 6 years ago

@PatNeedham You must click on Edit Scheme... not Manage Schemes... to edit the build order. You are not suppose to have any build-end target in the screenshot you send.

Look at mine:

capture d ecran 2018-04-26 a 23 49 38
peacechen commented 6 years ago

The generated files are a nightmare after upgrading to React Native 0.55. birkir's script does the job of generating the DotEnv files, but using it as a new target isn't able to handle different schemes.

To support different schemes, use his script without setting TARGET_ENV and place it in the scheme's Build -> Pre-action script box.

echo ".env.prod" > /tmp/envfile
./ios/react-native-config-gen.sh

And here's the modified react-native-config-gen.sh script:

#/bin/sh

RNCDIR="./node_modules/react-native-config/ios"

if [ ! -z "$SYMROOT" ]; then
  # Ensure directories exist before copying files
  mkdir -p $SYMROOT
  mkdir -p $BUILD_DIR

  # Build dotenv
  cd $RNCDIR
  ./ReactNativeConfig/BuildDotenvConfig.ruby
  cd -

  # Copy generated dotenv files to node_modules directory
  cp "$BUILD_DIR/GeneratedInfoPlistDotEnv.h" "$RNCDIR/ReactNativeConfig/GeneratedInfoPlistDotEnv.h"
  cp "$SYMROOT/GeneratedDotEnv.m" "$RNCDIR/ReactNativeConfig/GeneratedDotEnv.m"
fi

Note: Remove react-native-config from the Podfile, add it under Libraries, and add libReactNativeConfig.a to Linked Frameworks and Libraries.

vasilich6107 commented 6 years ago

Hi) I had a similar issue. When passed through the README installation instructions everything is ok. But after using command pod install I got the same error 'GeneratedDotEnv.m' file not found

If you are experiencing similar problems add this lines to the end of your podfile

post_install do |installer|
  installer.pods_project.targets.each do |target|
    if target.name == "react-native-config"
      target.remove_from_project
    end
  end
end
pontusab commented 6 years ago

@vasilich6107's Solution work, but don't be stupid like me and forget to remove the pod pod 'react-native-config', :path => '../node_modules/react-native-config'

scottmas commented 6 years ago

The simplest way around this I found was to simply temporarily delete my Podfile, and only THEN do yarn add react-native-config && react-native link. That way the library is added to ios via the manual linking method, instead of being added to your Podfile. After that, I restore my Podfile by simply doing git checkout ios/Podfile

mjgallag commented 6 years ago

FYI, this appears to be the same issue as #125.

eseQ commented 6 years ago

If you use fastlane try bundle exec fastlane comand

reilem commented 6 years ago

@vasilich6107 & @pontusab 's solution worked for me. Dragged an dropped the ReactNativeConfig.xcodeproj from node_modules to the 'Libraries' folder and added "libReactNativeConfig.a" (NOT libreact-native-config.a) under 'Link Binary With Libraries' in 'Build Phases'. And removing the left over reference in Podfile from the automatic linking.

Then using #import <ReactNativeConfig/ReactNativeConfig.h> to import instead of "ReactNativeConfig.h".

Martian2Lee commented 6 years ago

Thank you @scottmas , saved my day!

gatspy commented 6 years ago

@birkir perfect solution, thank you! issuecomment-353156419

Blargh1 commented 5 years ago

For pods: #125

jpmazza commented 5 years ago

Hey! I'm having this issue, too. 1_ I've set as Info.plist Preprocessor Prefix File: ${BUILD_DIR}/GeneratedInfoPlistDotEnv.h. 2 I have the react-native-config manually linking. 3 I have three different env files: .env.dev, .env.beta, .env.prod

I don't even find the GeneratedDotEnv.m file and GeneratedInfoPlistDotEnv neither. Where should be them located?

Any thoughts? Thanks in advance!

djGrill commented 5 years ago

Linking manually worked perfect for me; as suggested here.

smakosh commented 5 years ago

I followed your solution @birkir but now I'm getting this error

he following build commands failed:

    ExternalBuildToolExecution build-env
(1 failure)
birkir commented 5 years ago

@smakosh Go to the log explorer panel, select all (log, warnings and errors) and scroll up until you find the reason.

What you pasted is not why it failed, just that it failed and we can't help you with only this information I am afraid.

smakosh commented 5 years ago

I solved it by adding this post_install script to my podfile

post_install do |installer|
  installer.pods_project.targets.each do |target|
    targets_to_ignore = %w(React)

    if targets_to_ignore.include? target.name
      target.remove_from_project
    end

    if target.name == 'react-native-config'
      phase = target.project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase)
      phase.shell_script = "cd ../../"\
                           " && RNC_ROOT=./node_modules/react-native-config/"\
                           " && export SYMROOT=$RNC_ROOT/ios/ReactNativeConfig"\
                           " && export BUILD_DIR=$RNC_ROOT/ios/ReactNativeConfig"\
                           " && ruby $RNC_ROOT/ios/ReactNativeConfig/BuildDotenvConfig.ruby"

      target.build_phases << phase
      target.build_phases.move(phase,0)
    end
  end
end
vlad-fylp commented 5 years ago

A combination of @smakosh's reply and this: https://github.com/luggit/react-native-config/issues/125#issuecomment-436872749 helped

maxkomarychev commented 5 years ago

hey! please check out my pr: #349 it introduces new way of integration with ios project where you don't need to tweak various things in your podfile, also overall integration flow is shorter

thanks.

ghost commented 5 years ago

Is there anything I can do with this error?



ld: warning: directory not found for option '-L/Users/andrii/Library/Developer/Xcode/DerivedData/theftpatrol-apjuziaodvnhqxcakkzaaxjydwis/Build/Products/Prestige debug-iphonesimulator/yoga'

ld: library not found for -lReact

clang: error: linker command failed with exit code 1 (use -v to see invocation)```
ekowcharles commented 5 years ago

@birkir Thanks for the solution.

A quick note, running the solution as is results in the following error: Xcode 10.2: Unable to spawn process (Exec format error)

I had to change the first line in the *.sh script from #bin/sh to #!/bin/sh. Minor fix but huge gain.

salvariable commented 5 years ago

I'm having this error on RN 0.60... not sure how to try manual link since 0.60 introduces autolinking.

'react-native link react-native-config' doesn't work.

Any idea of what can be done?

jesusemendoza commented 5 years ago

@salvariable I'm on version 0.60.3 and Instead of using: react-react-native link react-native-config you can manually add: pod 'react-native-config', :path => '../node_modules/react-native-config' to your ios/Podfile but before you do a pod install I did what @smakosh suggested and added to the bottom of the Podfile

post_install do |installer|
    installer.pods_project.targets.each do |target|

      # The following is needed to ensure the "archive" step works in XCode.
      # It removes React & Yoga from the Pods project, as it is already included in the main project.
      # Without this, you'd see errors when you archive like:
      # "Multiple commands produce ... libReact.a"
      # "Multiple commands produce ... libyoga.a"

      targets_to_ignore = %w(React yoga)

      if targets_to_ignore.include? target.name
        target.remove_from_project
      end

      if target.name == 'react-native-config'
        phase = target.project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase)
        phase.shell_script = "cd ../../"\
                             " && RNC_ROOT=./node_modules/react-native-config/"\
                             " && export SYMROOT=$RNC_ROOT/ios/ReactNativeConfig"\
                             " && export BUILD_DIR=$RNC_ROOT/ios/ReactNativeConfig"\
                             " && ruby $RNC_ROOT/ios/ReactNativeConfig/BuildDotenvConfig.ruby"

        target.build_phases << phase
        target.build_phases.move(phase,0)
      end

    end
  end

Then do a pod install. Hope that works for you.

deepshikha139 commented 5 years ago

I tried to run pod install, and everything is working fine.

salvariable commented 5 years ago

Thank you @jesusemendoza! I'm still having trouble with the new way of installing / linking but this worked just fine :)

rnnyrk commented 5 years ago

@scottmas solution worked for my. To clarify the steps: Removed the package from my Podfile and manually linked it by dragging /node_modules/react-native-config/ios/ReactNativeConfig.xcodeproj to my Libraries in Xcode and linked the package libReactNativeConfig.a under Build Phases > Link Binary with Libraries.

argarner commented 5 years ago

After running the complete README install with react-react-native link react-native-config, I confirmed pod 'react-native-config', :path => '../node_modules/react-native-config' was in my podfile but it still didn't work. Adding the post_install do |installer|... block to the end of the file as per @jesusemendoza fixed it. Thank you Jesus!

digitaldavenyc commented 5 years ago

We've decided to move on from this repo, the amount of issues just installing is really crazy... for those that have had enough of the pain and suffering, react-native-dotenv is very simple to install and works well

argarner commented 5 years ago

We've decided to move on from this repo, the amount of issues just installing is really crazy... for those that have had enough of the pain and suffering, react-native-dotenv is very simple to install and works well

@digitaldavenyc does react-native-dotenv provide access to .env files within ios/android native code, like this package does?

alvelig commented 5 years ago

I've managed to solve it without linking like this https://github.com/luggit/react-native-config/issues/125#issuecomment-480632079

helderberto commented 5 years ago

I'm on version 0.60.5 of React Native.

I made the following steps:

  1. yarn add react-native-config@^0.11.7;

  2. react-native link react-native-config

  3. Add this code at the end of your PodFile:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    if target.name == 'react-native-config'
      phase = target.project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase)
      phase.shell_script = "cd ../../"\
                            " && RNC_ROOT=./node_modules/react-native-config/"\
                            " && export SYMROOT=$RNC_ROOT/ios/ReactNativeConfig"\
                            " && export BUILD_DIR=$RNC_ROOT/ios/ReactNativeConfig"\
                            " && ruby $RNC_ROOT/ios/ReactNativeConfig/BuildDotenvConfig.ruby"

      target.build_phases << phase
      target.build_phases.move(phase,0)
    end

  end
end
  1. cd ios && pod deintegrate && pod install

This works fine for me. :)

codeithuman commented 5 years ago

@helderburato, thank you! This worked for me on react-native 0.59.10 and react-native-config 0.11.7`.

MaffooBristol commented 5 years ago

The latest solution worked for me too, but I don't really know why it needed to 😕

It used to build fine but then I added react-native-navigation and it exploded!

jasonbodily commented 5 years ago

@helderburato 's answer works for me too, but since I'm using react-native 0.60+, my build now complains that it's linked. When I run react-native unlink react-native-config, it works and there's no complaining.

MaffooBristol commented 5 years ago

For the time being I've actually removed this module as it keeps springing up random errors and the original solution I used seems very unstable. So my advice is that although that podfile hack does work initially, it may not be worth the additional problems it causes.

Not sure what other solution there is right now though unfortunately :(