Cyclic dependency error J2OBJC archive build? - ios

I am having cyclic dependency issues with my Ionic/iOS project using J2OBJC as a internal Xcode settings built in.
I've set my build rules and settings in my ionic project as stated in the J2OBJC documentations. I have added the Library, User Header and framework search paths as required (firstly only app target, and also tried it with both app target and workspace) and created user defined $J2OBJC_HOME and (this probably isn't part of the requirements) I added a $PROJECT_DIR too. I also added the java build rule as such
"if [ ! -f "${J2OBJC_HOME}/j2objc" ]; then echo "J2OBJC_HOME not
correctly defined in Settings.xcconfig, currently set to
'${J2OBJC_HOME}'"; exit 1; fi; "${J2OBJC_HOME}/j2objc" -d
${DERIVED_FILE_DIR} -sourcepath "${PROJECT_DIR}/App"
--no-package-directories -use-arc --prefix Flowers=JOE -g ${INPUT_FILE_PATH};"
I have build both simulator and iPhone and ran them on both and they seem to be working. However, when I go to archive (so I can create the .ipa) for the project. I get a cyclic dependency error. I have tried numerous things, such as, fresh start of project, using different URLs for the search paths, using recursive and non-recursive, checked the documentations a few times, looked at forums and still have no solution. Any ideas would be greatly appreciated!

Xcode can no longer handle the same header search path in Header Search Paths and User Header Search Paths. You probably have "$(J2OBJC_HOME)/include" in both of these. So remove it from Header Search Paths and leave it in User Header Search Paths.

I've had this cyclic dependency issue for a good month and a half. I've tried almost everything.
I've looked everywhere.. and got 2 replies from Tom Ball. When it comes to a big project converted from java to Objc using the tool, xcode won't recognize the sub-directories made. I figured out the best fix is to create your own script using bash. I did some research and figured out how to recursively find all java files and apply the j2objc script to them and it will output all of your Objc files in the same directory layout. (Keeping a nice layout for you instead of the messy-everything-in-one folder like j2objc script rule on Xcode works).
My build.sh file is as follows, feel free to copy it-
!/bin/bash
Clean out Objective C folder
rm -rf /ObjC_Output
Move into Java Folder
cd Java
Run j2objc and output everything into ObjC
j2objc -d ../ObjC_Output $(find . -name "*.java")
Jump out of Java folder
cd ..
Delete previous org
rm -rf /Users/me/Projects/project-name/mobile-app-front-end/app/ios/app/app/org
cd to ObjC_Output
Copy new ObjC Project files over to the XCode project..
cp -R ./ObjC_Output/* /Users/me/Projects/project-name/mobile-app-front-end/app/ios/app/app/org
I automatically copy all my files back to my Xcode project.. feel free to do it anyway you want. Also don't forget to add j2objc to your path. and run your script as such ./builder.sh in terminal..
Also for Xcode to recognize your objC project folder you must add the top directory of your Xcode project and make it recursive.
In this case, you don't need to include the j2objc script in Xcode.. Just make sure you include all the default Linker paths, Library search paths and User Header search path as usual (shown in the j2objc documentation).
I've had to pull my hair out for this solution.. So feel free to ask for help if needed.

Related

How to access my app’s derived data folder itself?

I’m in the middle of moving my iOS app’s Firebase dependency from CocoaPods to Swift Package Manager.
Firebase’s Crashlytics requires a script to be executed while the app is building (using the Run Script build phase). Back in the CocoaPods days, I used to call the script the way documented by Google: "${PODS_ROOT}/FirebaseCrashlytics/run".
After I’ve switched to SPM, Firebase files are no longer in ${PODS_ROOT}, and there’s no such variable available at all. I know the file I need is now located in the DerivedData folder, specifically it’s at ~/Library/Developer/Xcode/DerivedData/MyApp-abcde/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run. The problem is, the MyApp-abcde folder is not easily referenced.
A Medium post I found suggested using the ${BUILD_DIR} build variable (in regard to the example above, it would resolve to <…>/MyApp-abcde/Build/Products), and calling the dirname command to move up the directory hierarchy.
This hack worked only for running the app. When I tried to archive it, ${BUILD_DIR} resolved to another path, namely <…>/MyApp-abcde/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/BuildProductsPath. I tried a few more build variables, such as ${SYMROOT}, in place of ${BUILD_DIR}, but they also produce different paths depending on the operation.
So, here comes the question…
Is there a way to reliably reference my app’s derived data folder’s root (i.e. ~/Library/Developer/Xcode/DerivedData/MyApp-abcde) using Xcode’s build variables?
You were close. This should work:
${BUILD_DIR%Build/*}SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run
Crashlytics run script
To build&run from Xcode:
${BUILD_DIR%Build/*}SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run
To archive for distribution from Xcode Server at CI/CD:
${XCS_DERIVED_DATA_DIR%/*}/Dependencies/checkouts/firebase-ios-sdk/Crashlytics/run
To work for both at the same time:
if [[ "${XCS_DERIVED_DATA_DIR}" == "" ]]; then
${BUILD_DIR%Build/*}SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run
else
${XCS_DERIVED_DATA_DIR%/*}/Dependencies/checkouts/firebase-ios-sdk/Crashlytics/run
fi
I'm reworking my answer as I realized I haven't answered your question..
I have a run script that copies the build targets into a new folder. This works for both Build and Archive. Note that you need the -L on copy to follow the symlink
# Copy the built framework into a sibling to the project folder
if [[ "$CONFIGURATION" == "Debug" ]]; then
mkdir -p "$PROJECT_DIR/../../iwins-ios-sdk/debug"
rm -rf "$PROJECT_DIR/../../iwins-ios-sdk/debug/IWiNS_SDK.framework"
cp -LR "$BUILD_DIR/Debug-iphoneos/IWiNS_SDK.framework" "$PROJECT_DIR/../../iwins-ios-sdk/debug"
else
mkdir -p "$PROJECT_DIR/../../iwins-ios-sdk/release"
rm -rf "$PROJECT_DIR/../../iwins-ios-sdk/release/IWiNS_SDK.framework"
cp -LR "$BUILD_DIR/Release-iphoneos/IWiNS_SDK.framework" "$PROJECT_DIR/../../iwins-ios-sdk/release"
fi
Also, you can find all of the build envvars here:
https://gist.github.com/gdavis/6670468
So, it appears that $BUILD_DIR is different for build/release, but by copying the files to a known location at build time, you'll know where to find them.

After importing Objective C Framework into my Swift project, my project does not recognise my header file in my Bridging file

I've got to import a Framework into my Swift project that is written in Objective C. So I've created a Bridging file and after I've added the Header files to it and compiled, my project says it cannot find them. The image below shows my Framework and you can clearly see AWController.h but it throws an error in my Bridging file when building.
The Bridging file shows in my Settings so what am I doing wrong or what have I missed? I've set my Defines Module to Yes in Build Settings and my Module Name has no spaces.
I would review the setup for AWS at their website. They even have a section that details using with Swift iOS9.
Among other things, if you are using the Frameworks manual integration, verify that step 4 is complete.
Under the Build Phases tab in your Target, click the + button on the
top left and then select New Run Script Phase. Then setup the build
phase as follows. Make sure this phase is below the Embed Frameworks
phase.:
Shell /bin/sh
bash
"${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/AWSCore.framework/strip-frameworks.sh"
Show environment variables in build log: Checked Run script only when
installing: Not checked
Input Files: Empty Output Files: Empty
You might want to install and use Carthage to make this easier. Head over to the Homebrew website then after installing homebrew you'd run brew install carthage from the command line. After that go back to the link above and follow the Carthage instructions.
Secondly, I would take another walkthrough of the Apple Documentation on Working with the bridging header files to see if any of the edge cases apply and just as a sanity check.
Third, if that doesn't work, I'd just try creating an empty Swift project and walk through the steps again using one of the techniques above. There might be something wrong with one or more settings in your project files or the file itself might be corrupt.
BTW - The product bundle identifier should probably be following the convention of com.yourdomain.YourProductName.
You should not use bridge header. Just use import AWSDK in the swift file where you use it.

Using CMake to copy .frameworks to iOS app bundle

A library I'm using recently switched to distribution as a .framework.
In my existing CMake file, I've been successful at getting it to link with my iOS app, but am getting:
dyld: Library not loaded: #rpath/Pizza.framework/Pizza
Referenced from: /var/mobile/Containers/Bundle/Application/D71ED298-C287-4B2F-8AFA-710A14C06D75/pizzashop.app/pizza
Reason: image not found
when I install it from Xcode. If I manually add it to my xcode project, in the "embedded binaries" section then I'm good (see image below)
So I've concluded that the problem is getting the .framework into my app bundle. I've come across this question and looked at the linked QT example, but I'm still trying to orient myself here as I'm finding the syntax a bit opaque.
Is CMake's BundleUtilities what I want to use here? In looking at the BundleUtilities example I'm a bit lost:
set(APPS ...) # paths to executables
set(DIRS ...) # directories to search for prerequisites
INSTALL(CODE "
include(BundleUtilities)
fixup_bundle(\"${APPS}\" \"\" \"${DIRS}\")
" COMPONENT Runtime)
Is this OSX-specific or can I apply it similarly to iOS?
We didn't end up finding an ideal solution, and ended up doing things a bit more manually than preferred:
We added a custom command we run after the build is complete, but before it is packaged (see CMake's add_custom_command).
The custom command does the following:
creates a Frameworks directory under our app bundle folder (make sure it's somewhere where it will get copied in your packaging process).
we use cp -aH to copy all frameworks into this Frameworks directory
we then re-sign each framework in this directory using:
codesign --force --verbose Computers.framework --sign "$2"
Add the Frameworks directory to your search paths:
set_target_properties(${EXE_NAME} PROPERTIES
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "#executable_path/Frameworks")

Xcode framework Versions/Current/Headers/ error

I am confused about adding a third party framework into Xcode project.
Here are the steps:
1) I copy the framework into project subfolder called "Frameworks". So framework is added to repository.
Everything works fine, app compiles, here is the screenshot:
2) I push the changes into repository (I use mercurial)
3) If I pull the changes on other machines or just switch between branches then project doesn't recognize this framework any more.
Here is the screenshot:
The question is why it happens and how to solve this problem? I there any specific way to add a framework in this case?
Thanks in advance!
I had this problem today and it was because the 3rd party framework was delivered as a .zip file and symbolic links inside of the framework were lost at some point.
Here is Apple's documentation on the anatomy of a framework:
https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html
The document explains that multiple framework versions might exist inside of the framework bundle, so the bundle contains some symlinks pointing to the current version of some directories.
MyFramework.framework/
MyFramework -> Versions/Current/MyFramework
Resources -> Versions/Current/Resources
Versions/
A/
MyFramework
Resources/
English.lproj/
InfoPlist.strings
Info.plist
B/
MyFramework
Resources/
English.lproj/
InfoPlist.strings
Info.plist
Current -> B
The problem you have is exactly like mine. Confirm that the three symlinks that Apple documented (MyFramework, Resources, Versions/Current) are not symlinks, but are tiny files. Then delete the tiny files and replace them with symlinks to the current framework version. For example, if the current version is 'A':
cd NewRelicAgent.framework
rm Headers
rm NewRelicAgent
rm Versions/Current
ln -s Versions/Current Versions/A
ln -s Headers Versions/A/Headers
ln -s NewRelicAgent Versions/A/NewRelicAgent
If there are multiple versions in your framework, then the text in Versions/Current might contain the current version. This would be an artifact where the compression tool is storing the symlink as text instead of an actual link.
We are facing a similar kind of issue. The result we get is the same, but the setup is different.
Posting our findings here, incase someone else finds it useful.
Our apps high level setup
React Native app
Git repo
npm for package management (npm install)
lots of .xcodeproj under one .workspace
one of those .xcodeproj have a .framework that shows the issue mentioned above
Our findings (so far)
it's not the actually git checkout thats causing this stripping out of symlinks in .framework behaviour
it's actually how our package manager (npm) installs the said sub repo. It might be npm is doing something to strip out symlinks in install or post install phase.
If we download or git checkout the said sub repo manually, framework symlinks are in tact.
Our initial approach to fix the issue
Include a symlinks intact version of the framework (Valid.framework) in the main project.
use npm install to install the packages as normal (this would strip out the symlinks in the framework Broken.framework file thats in the sub repo)
have a post install script copy and/or override Broken.framework with Valid.framework
cp -Rf <path_to_working_framework>/Valid.framework/* node_modules/<path_to_broken_framework>/Broken.framework/

CMake: How can I copy a directory into the ios application bundle

I have an ios project that builds with CMake 3.1.1, but I am stuck on the last problem - getting CMake to copy the asset directory into the right location for the app.
I have this, which works when running the app in the simulator. However, it does not work, and in fact causes a build failure when archiving because the destination directory it constructs does not exist.
get_target_property(APPLICATION_BIN ${APPLICATION_NAME} LOCATION)
get_dotapp_dir(${APPLICATION_BIN} APPLICATION_APP_LOCATION)
add_custom_command(TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND cp -r "${CMAKE_SOURCE_DIR}/assets" "${APPLICATION_APP_LOCATION}")
The directory I am copying has many subdirectories and I need them all preserved. Essentially I want to accomplish with cmake the same thing that happens when I drag the "assets" folder into the ios project underneath "Resources".
Use ${CMAKE_COMMAND} -E copy_directory instead of calling cp.
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${LOCATION_FOR_THE_APP} DEPENDS "${PROJECT_SOURCE_DIR}/assets" COMMAND -E copy_directory ${PROJECT_SOURCE_DIR}/assets ${CMAKE_CURRENT_BINARY_DIR}/${LOCATION_FOR_THE_APP})
add_custom_target(${CMAKE_CURRENT_BINARY_DIR}/${LOCATION_FOR_THE_APP} DEPENDS
My solution to this is similar to this answer. The goal of my project was to get googletests running on a cross-platform library, in which I had to wrap googletests into an XCTest Bundle. The build tool we are converting to is CMake for obvious reasons.
I ended up doing this as a pre-build step:
add_custom_command(TARGET ExampleTestTarget PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_LIST_DIR}/resources $<TARGET_FILE_DIR:ExampleTestTarget>
)
Essentially, at prebuild, CMake will copy everything in the resources folder into the root of the target's bundle. For some reason (probably a CMake thing), XCode picked these resource files up with no issue, so I didn't have to set the files to be RESOURCE files explicitly.
If you're using MacOS Bundles/Packages/etc., you'll have to copy-paste these files into $<TARGET_FILE_DIR:ExampleTestTarget>/Resources instead since this is the default resource location for MacOS xcodeproj's generated by CMake. (There are so many loopholes to get XCTests working in CMake that I advise everyone doing cross-platform gtests to create an executable instead for MacOS so you won't get into any trouble like this anyway).
Note, you won't see the files in XCode unless you add the files in target_sources(), but who cares... it works anyway! Who develops C++ exclusively in iOS? ....

Resources