Should I git ignore xcodeproject/project.pbxproj file? - ios

in a XCode project, I offen got xcodeproject/project.pbxproj file changed, but useless info for me, it for compile.
Should I git ignore this file and xcodeproject/projectxworkspace/username.xcuserdata/UserInterfaceState.xcuserstate file?

Update in the light of Swift Package Manager: If you're building a project as a Swift package - you should definitely ignore this file as it can be generated using file system as source of truth. You can do that by using the following command:
$ cd ~/Projects/MyProjectFolder/
$ swift package generate-xcodeproj
For non-SwiftPM answer - see below.
This file holds the list of all the files in the project, settings of targets and which files belong to which targets. It's probably the meatiest file in project bundle. You should not ignore this file. There are few points for this:
You may not want to work on this project alone or;
You're planning on working on project from different machines;
You'll want to share your code base with others;

That is the only file that you want in your repos from the xcodeproj bundle. That file holds all of the info for targets files and build settings.

Unfortunately, if your Build Settings includes code signing, you have to re-enter your code-signing entity after every "git pull" if another team member has changed it. It seems to me this info should be in the user settings, not the global pbxproj file.

project.pbxproj is an important file in the Xcode configuration bundle. It is responsible for maintaining references to all of the linked files and their groupings, linked frameworks, and most importantly, the project’s build settings. Because of this, we cannot exclude project.pbxproj from version control.
Here is my general .gitignore for my Xcode Project.
# OS X Finder
.DS_Store
# Xcode per-user config
*.mode1
*.mode1v3
*.mode2v3
*.perspective
*.perspectivev3
*.pbxuser
*.xcworkspace
xcuserdata
# Build products
build/
*.o
*.LinkFileList
*.hmap
# Automatic backup files
*~.nib/
*.swp
*~
*.dat
*.dep

If you exclude project.pbxproj Jenkins builds will fail. So this is important if you use Jenkins.

You can use Xcodegen to generate a pbxproj out of a YAML project specification file then you can ignore pbxproj in git and generate them every time you need.
I have already used Xcodegen on a second project which has a modular architecture (many pbxprojs) and more then 8 developers is working on it.
https://github.com/yonaskolb/XcodeGen
Hope it helps.

I found that I also need to preserve the xcworkspace file(s). If didn't, project with a sub-project broke.

Related

There are missing files when I archived from custom build configuration

We have different build configurations in our project, like the release, debug, sandbox, etc. The interesting case is when I archived from the release or debug build configuration, all archive files extracted as expected as shown in Image 1, but If I change build configuration to sandbox, some files and folders are missing as shown in Image 2.
Although we created custom build configurations by duplicating from debug or release, the archive doesn't contain all files or folders like in Image 1.
We use carthage(for internal network) and cocoapods(for others) as a dependency manager.
I tried many suggestions but couldn't find a solution.
Like,
setting skip install to NO in build settings,
removing all archive and derived data files, clean and re-archive,
giving the archive folder to read & write permission
Thank you all
If you're using Carthage for internal frameworks you should have same custom build configurations for them, too. Otherwise, it will bootstrap with Release configuration automatically which won't generate SwiftSupport files etc.
You also can avoid this by adding below before archiving in your custom configurations.
carthage bootstrap --configuration Debug
You should make sure that those files are included in Build Phases -> Copy Bundle Resources

What's the equivalent of "development pods" under Carthage?

The teams developing frameworks for our iOS app are migrating from Cocoapods to Carthage.
Under Cocoapods, I could set up dependencies as "development pods". For example, instead of having the main app download a specific version of an xyzzy dependency, I could set up xyzzy as a development pod and point it to my local directory where I had checked out xyzzy from its Git repo. While I was working in the main app's project, any edits I'd do to xyzzy's files would be made in that directory. This let me build and test changes immediately, and when I was ready to check them in, Git would find them in the xyzzy project's directory.
Under Carthage I haven't found a way to do this. I see http://allocinit.io/ios/debugging-carthage-dependencies/ which explains how to create symbolic links so that I can see the dependency source files to make debugging easier, but any edits I make to them are under the main application's Carthage/Builds directory.
How do I set up the equivalent of development pods under Carthage?
I believe Carthage doesn't have something similar to "development pods" yet.
But you could simulate "development pods" just following these steps:
Steps:
Add the .xcodeproj to your workspace
Remove all the dependencies you have in your project of the framework you added in step 1. (probably you may need to remove it from Build Phases -> Run Script -> Input Files too )
Go to General tab of the target you want to run, add the framework under Linked Frameworks and Libraries (it is going to take the one added from the .xcoproj)
(optional) you may need to run carthage bootstrap in the framework's repo you want to add locally.
That's it.
After that you will be able to run your project and update framework's code in the same workspace.
This works just as well as development pods for me, as of Xcode 8.3.3 and Carthage 0.24.0:
In app path, rm -rf Carthage
Point at the appropriate branch or tag in Cartfile
carthage update --use-submodules (generates .gitmodules and clones repo into Carthage/Checkouts)
In Xcode under project -> Build Phases -> Run Script, comment out the line that ends with carthage update --cache-builds if present.
Change to the General tab and remove the lib from Embedded Binaries
Right-click project, Add Files to app..., add lib from Carthage/Checkouts
Under project -> General, re-add the library, choosing the one you added in the previous step.
App should now build with the local lib. Make sure that your .gitignore has Carthage/{Build,Checkouts} and .gitmodules.
This answer is a summary of a successful implementation of the solution introduced here.
A cleaner solution is using local paths for dependencies in Cartfile.
Environment
Xcode 10.1
macOS 10.13.6
Step 1. Symbolic linking
1.1 Change $(SRCROOT_MAIN)/Carthage/Checkouts/$(DEVELOPING_FRAMEWORK_NAME) directory to a symbolic link pointing to source root directory of your developing framework $(SRCROOT_DEVELOPING_FRAMEWORK), where $(SRCROOT_MAIN) is source root directory of your main app. Backup existing directories before this change.
This linking enables version-controlled changes in your developing framework.
Syntax when using ln utility,
$ ln -s "$SRCROOT_DEVELOPING_FRAMEWORK" "$SRCROOT_MAIN/Carthage/Checkouts/$DEVELOPING_FRAMEWORK_NAME"
1.2 Change $(SRCROOT_DEVELOPING_FRAMEWORK)/Carthage/Build directory in your framework to a symbolic link pointing to $(SRCROOT_MAIN)/Carthage/Build directory. Backup existing directories before this change.
This linking enables access to all frameworks built by Carthage from both your developing framework and your main app.
Syntax when using ln utility,
$ ln -s "$SRCROOT_MAIN/Carthage/Build" "$SRCROOT_DEVELOPING_FRAMEWORK/Carthage/Build"
Step 2. Framework Replacement

2.1 Remove your developing framework in Xcode > YOUR_MAIN_APP > General > Linked Frameworks and Libraries (that is, the one located in $(SRCROOT_MAIN)/Carthage/Build/iOS).
2.2 Add $(DEVELOPING_FRAMEWORK_NAME).xcodeproj (found in directory pointed by $(SRCROOT_MAIN)/Carthage/Checkouts/$(DEVELOPING_FRAMEWORK_NAME) symbolic link) into your main app
2.3 Build the developing framework product for device and simulator
2.4 Add the new developing framework auto-detected by Xcode in Xcode > YOUR_MAIN_APP > General > Linked Frameworks and Libraries.
2.5 Add $(DEVELOPING_FRAMEWORK_NAME).framework as a target dependency by adding $(DEVELOPING_FRAMEWORK_NAME).framework in Xcode > YOUR_MAIN_APP > Build Phases > Target Dependencies.
2.6 Copy $(BUILT_PRODUCTS_DIR)/$(DEVELOPING_FRAMEWORK_NAME).framework to $(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/$(DEVELOPING_FRAMEWORK_NAME).framework by adding a new input file $(BUILT_PRODUCTS_DIR)/$(DEVELOPING_FRAMEWORK_NAME).framework and a new output file $(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/$(DEVELOPING_FRAMEWORK_NAME).framework in Xcode > YOUR_MAIN_APP > Build Phases > Run Script of Carthage Embed Framework.
Reference
Debugging Carthage Dependencies
https://allocinit.io/ios/debugging-carthage-dependencies/
Build Setting Reference
https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html

Using agvtool with multiple .xcodeproject files in one directory

I have tried using agvtool for ios build versionining. It works great when there is a single .xcodeproj file in the directory. In my case, our project structure is such that it has 4 .xcodeproj files in a single directory. When firing agvtool command in this directory it throws error message, 'agvtool does not work with multiple projects in the same directory'. Anyone has any idea how can I make agvtool work with this folder structure?
For people finding this post and using Fastlane, I just wanted to tell about the plugin https://github.com/SiarheiFedartsou/fastlane-plugin-versioning which have a increment_version_number_in_plist command which does not use agvtool (and support multiple .xcodeproj files in a single folder.
You just need to install the plugin above and replace your increment_version_number action with increment_version_number_in_plist .. they have a very similar contract.
For me, there were actually 2 xcode project files. i.e. projectName.xcodeproj and projectNameModule.xcodeproj. That happened as I removed some commits where we updated the project name from projectName to projectNameModule. For some reason even after reverting those name changes, the project *Module.xcodeproj and *Module.xcworkspace files were still existing.
I just deleted those unused files and it fixed the issue for me.

Issues Using GIT with Xcode projects

I know git and use it to manage a lot of my Repos on other projects. However I run into issues when it comes to xcode projects.
I start a project on Machine 'A' - when I push up to a repo and pull to let say machine 'B' I always receive compiling errors. Normally the errors have to do with files not being found. Literally "no such file or directory" followed by a path.
I'm working with the same version of Xcode on both mac's A and B. I also use the threetwenty framework.
When I zip the project up and send via email - the same results occur.
Many times these files that xcode can't find and that fail the build, are media files, like a image or video. Sometimes I see the three20 framework too.
My question is - how in xcode should I set a project up to play nice with git and or code sharing in general. Let me know if you need more information, I know the above is a little vague.
The first thing I always do is set up the .gitignore file before adding any other files from the project. Problems can occur when loading project settings for two different machines that may have the same User account name. You have to make sure some settings aren't added to the repo whilst others are.
I set up my .gitignore by adding the following:
.DS_Store
*/.DS_Store
*.swp
*~.nib
build/
*.pbxuser
*.perspective
*.perspectivev3
*.mode1v3
*.mode2v3
Documentation/Generated
doxygenWarnings.txt
*.xcodeproj/xcuserdata/*.xcuserdatad
*.xcodeproj/project.xcworkspace/xcuserdata/*.xcuserdatad
*/*.xcodeproj/xcuserdata/*.xcuserdatad
*/*.xcodeproj/project.xcworkspace/xcuserdata/*.xcuserdatad
If you create the repos from scratch or run git rm --cached <filethatshouldbeignore> to each file that should be ignored and then commit, see if the problem still occurs.
Problems will occur in the .pbxproj file, so make sure all conflicts are corrected too.
Regarding files that cannot be found, remember to import the libraries etc. into the project folders and reference them from there. Apple's own iOS libraries should be fine, but others won't be. For example, in your project folder, copy your images from there and reference them only within the project folder.

How can I get my project's folder structure to be mirrored in Finder?

I have an Xcode (4.2) project with a bunch of class files, and I have them neatly organized into folders. These folder aren't "real", however; in Finder, my classes are all just dumped into the one "Classes" folder. Is there any way to get the virtual folder structure I see in Xcode to be reflected in the real Finder folder structure? Or do I have to do this manually?
https://github.com/venmo/synx
A command-line tool that reorganizes your Xcode project folder to match your Xcode groups
Installation
$ gem install synx
Usage
Basic
:warning: WARNING: Make sure that your project is backed up through source control before doing anything :warning:
Execute the command on your project to have it reorganize the files on the file system:
$ synx path/to/my/project.xcodeproj
It may have confused CocoaPods. If you use them, execute this command:
$ pod install
You're good to go!
Advanced
Synx supports the following options:
--prune, -p remove source files and image resources that are not referenced by the the Xcode project
--no-color removes all color from the output
--no-default-exclusions doesn't use the default exclusions of /Libraries, /Frameworks, and /Products
--quiet, -q silence all output
--exclusion, -e EXCLUSION ignore an Xcode group while syncing
For example, OCMock could have been organized using this command:
$ synx -p -e "/OCMock/Core Mocks" -e /OCMockTests Source/OCMock.xcodeproj/
if they had wanted not to sync the /OCMock/Core Mocks and /OCMockTests groups, and also remove (-p) any image/source files found by synx that weren't referenced by any groups in Xcode.
I often want to do the same thing, but as far as I know there is no automatic way to do it, you have to do it manually unfortunately...
There is no 'automatic' way to make the XCode file pane structure automagically conform to the finder folder structure, although I agree there should be a setting for this.
I follow these steps when making a project:
Create the project.
Delete by reference any files I want to move.
Open finder and move the files, then drag them back into XCode.
When adding new files:
Create a folder in finder if needed.
Drag the folder into XCode.
Right-click and make a new file on the group that represents the folder just dragged in.
If you're using git, it's a little more work:
Commit your project before making a folder or file deletions/moves.
Delete them by reference from XCode.
Move them in finder.
Using terminal, type git mv sourcePath destPath to move files or git rm sourcePath to delete them.
Then drag back into XCode.
You can see more about my frustration with learning git here:
How can I move files & folders using git in Xcode 4?

Resources