Xcode, git, and intermediate build folders - xcode

I would like two things:
to be able to change branches in git, and then Run or Build in Xcode without recompiling the entire project.
have git ignore intermediate build files during merge, so it won't ask me to resolve any conflicts.
Putting the intermediate builds folder outside the project, or using .gitignore to ignore that folder, accomplishes #2 but not #1; I have to rebuild the entire project when I change branches, even if I did not modify any files.

Well, you've answered #2 correctly yourself, so really your question only related to #1. I don't really see why Xcode would need to recompile things either - git won't change timestamp on unchanged files when switching branches.
Have you actually implemented the #2 solution, so that the entire problem isn't caused by git stomping on your build directory, which should be .gitignore'd?

You could define two variables:
MY_BRANCH_NAME = branch_foo (adapted in each branch)
TARGET_TEMP_DIR = $(CONFIGURATION_TEMP_DIR)/$(TARGET_NAME)$(MY_BRANCH_NAME).build (the same for all branches)
This way, the builds for your different branches will be made and keeped in separate folders, not needing to recompile everything because of a branch-to-branch config change.
You can do it in xcconfig files, or automatically define MY_BRANCH_NAME as an xcodebuild argument in a build script, among other means.

Xcode is going to do all of its data based on the timestamps of the files in question. If you replace the file with a newer file, then Xcode should notice that the timestamp of the file is newer than the timestamp of the build product and recompile it.
However, if you change it with an even older version of the source file, then it can't know that the build file isn't correct. It will just see that the build output is still newer than the source file, and so not recompile it.
In short, you can't know which files have definitely changed, and which have definitely not. You're better off doing a full clean+rebuild to make sure; otherwise you're going to lose time debugging when it doesn't work.

Related

Trick gmake build/ Copying files to preserve time stamps and avoid complete rebuild

short background info:
For some rather convoluted reasons I am trying to trick my projects build system. We are working with Code Composer Studio on Windows from Texas Instruments and the gmake implementation that was included. We use the standard Debug build option pretty much unmodified as far as I am aware of (my understanding of make and our implementation of it is unfortunately limited). When developing in Code Composer the build works as one would expect, only the files that have been changed and their dependencies are changed. Sometimes I need to regenerate all code from a code generator that we use however, triggering a complete rebuild.
Trying to trick this complete rebuild I wrote a python script that moves all the original files out from the project, waits for the code generator, then compares the files and replaces the new identical files with the old ones. Thus the creation timestamp and the last modified timestamp should be preserved. This also seems to work when examining these properties. However a complete rebuild of the problem is always triggered.
Core of the Problem:
Having already built the project in Code Composer and building again it concludes that nothing has changed and that there is nothing to do, as one would expect.
I move a file out of the folder and back in again, preserving both the creation time stamp and last modified time stamp as far as I can see (in windows explorer -> properties).
When now rebuilding the project it will rebuild the said file and its dependencies, despite it being identical to before and having the same timestamps.
What is gmake looking at? Does it detect that the folder has been changed. Is it looking at some other hidden timestamp? Is it a Windows problem? Shouldn't it be possible to do this, inserting a file with an old timestamp?
What am I missing? Anyone have a clue?
Having examined this I concluded that the problem does not lie with gmake or the makefile but with Code Composer Studio's/Eclipse makefile generation.
We use the built in makefile generation in Code Composer Studio (which is an Eclipse derivative). It seems to keep track of if files have been removed/moved out from the projects workspace. If it has it removes the dependecies of that files during the makefile generation, triggering a rebuild.
Examples:
Case 1, works as I expect:
Rebuilding an unchanged project in Code Composer Studio. Nothing is recompiled since nothing is changed.
Case 2, works as I expect:
Changing something in a single then rebuilding results in recompilation of only that single file. As I/once expects.
Case 3, does not work as I expect:
Having an unchanged project and the moving one source code file (xyz.cpp) out of the project, not changing it in any way and then mvoing it back results in a recompilation of xyz.obj.
Code Composer/Eclipse seem to keep track on the filestructure. Despite the file being put back into the project exactly the way it was, Code Composer/Eclipse deletes xyz.obj during the makefile generation, triggering a rebuild.
On the other hand; closing Code Composer, moving the file back and forth, Reopening Code Composer and regenerating makefile/rebuilding works as one expects. Nothing is rebuilt and no .obj files are removed.
Since this didn't have anything to do with gmake and makefile I guess this question was invalid/unrelevant to begin with. I will collect my thoughts and reformulate a new question formulated strictly as a Code Composer/Eclipse errand.
If anyone has found themselves in the same situation or have relevant information on their hands please share however!

How to use gitignore files in Xcode 5

I am still pretty new to using git, and I am a little confused on how to ignore files. I know you make a file named .gitignore, and usually have it at the root directory of your project, but is that it?
Am I supposed to add it to my Xcode project in Xcode 5? Most of my research has shown what should be IN the .gitignore (like Gitignore/Objective-C.gitignore), but the closest I've found to my question is: How to add .gitignore file into Xcode project.
While that does say HOW to do it, is this what one does? Or do you just leave it in the base folder and it doesn't matter whether it is in the project or not?
.gitignore files are processed regardless of whether or not they're tracked. They're usually tracked, just as the main branch is usually called master, and since if they're not tracked they're vulnerable to e.g. git clean I can't figure why anyone would leave them untracked, but it's irrelevant. Only what's in them matters.

Should git ignore the *.pch files created by XCode?

Should I add *.pch files to .gitignore in XCode projects?
No, you should not. It's not a generated file, you as a developer may (and should) modify it. The point is to put the most commonly used #import/#include directives in here. That will speed up compiling as Xcode will then precompile it and GCC will use these "cached" results when compiling other files without the need to parse and compile those includes over and over again.
I found the speedup to be especially dramatic with C++, BTW.
To add a bit more context to the question - What files should you consider ignoring in a VCS?
Personal settings files such as *.pbxuser. These are things that contain the settings for your personal environment or workspace. Not much use to anyone who clones the repository and of marginal use if you are using a repository across machines
Generated files. If your project generates files then there is no point in having them in your repository because unless you are always generating them, they end up out of date. This is why you frequently see build/ in the .gitignore file
Files that contain passwords or access tokens. Pretty obvious, really.
Put it simply. Don't ignore anything that your project requires to build. The PCH file is referenced in your project settings and you'll get a build error if it doesn't exist in the project so it really should be in the repository.
No, they're important to the project.
They're prefix headers and will be imported to every file within the project.
I don't use git, I use svn but the ignore settings should be the same. When I set up a project, the only things I ignore by default are:
the build directory
*.pbxuser and *.mode1v3 in the xcodeproj bundle.
Everything else (including the pch file) is something that should be under source code control (unless you add other generated files outside of build).

How do you keep Xcode project source files in sync with your file system directories?

I'm new to XCode and I find the file management a huge pain. In most IDEs, you can simply have the project source tree reference a directory structure on disk. This makes it easy to add new files to your project - you simply put them on disk, and they will get compiled automatically.
With XCode, it appears I have to both create the file and separately add it to the project (or be forced to manipulate the filesystem through the UI). But this means that sharing the .xcodeproj through source control is fraught with problems - often, we'll get merge conflicts on the xcodeproj file - and when we don't, we often get linker errors, because during the merge some of the files that were listed in the project get excised. So I have to go and re-add them to the project file until I can get it to compile, and then re-check in the project file.
I'm sure I must be missing something here. I tried using 'reference folders' but the code in them doesn't seem to get compiled. It seems insane to build an IDE that forces everyone to modify a single shared file whenever adding or removing files to a project.
Other answers notwithstanding, this is absolutely a departure from other IDEs, and a major nuisance. There's no good solution I know of.
The one trick I use a lot to make it a little more bearable — especially with resource directories with lots of files in them — is:
select a directory in the project tree,
hit the delete key,
choose "Remove References Only", then
drag the directory into the project to re-add it.
This clobbers any manual reordering of files, but it does at least make syncing an O(1) operation, instead of being O(n) in the number of files changed.
I'm intrigued which IDEs you're using that automatically compile everything in a directory, as no IDE I've ever used does that (at least for C++). I think it's pretty standard to have a project file containing a list of all the files. Often you may want to only include certain files for different targets, have per-file compiler settings, etc.
Anyway, given that that's how it does work, you really shouldn't have too many problems from merge conflicts. The best advice would be commit early and often so that you don't get out of step with other people's changes. Merely adding files to the project shouldn't result in a conflict unless they happen to be added at exactly the same point in the project tree. We've been using Xcode in our team for years and we very rarely get conflicts: only if someone has restructured the project.
Fortunately, because the Xcode file format is text, it's generally quite easy to resolve conflicts when they occur, unlike the Bad Old Days of Codewarrior with it's binary format.

Git Merging of Binary Files (in particular Xcode project files)

I've got an Xcode project under git and I've got a "experimental" branch off of my "master" branch. Both branches have diverged since the branch (so no fast-forwarding!), and I am merging "experimental" into my "master" branch.
I've setup a .gitattributes file to treat a particular Xcode file (project.pbxproj) as binary, as it should be treated as such. However, I'm not sure exactly how to merge it. I'm not sure what that particular file does, but if for example it handled which files were added to the project there's no way I can merge them, and therefore I'd have to manually add certain files back to the project (possibly not remembering them all). How do others handle this situation?
Also, I've read that you have to manually update binary files (obviously) or copy over different versions. However, once I'm into the merge process the file in my working copy is the "master" version. How can I access the "experimental" version? I can't check it out as it would disrupt the merging process.
Thanks for your time!
In general, for binary files, I recommend a copy-merge type of .gitattribute directive.
That is, I just copy the file coming from the remote end of a merge.
For .pbxproj files however, that may not be a good option, as described here.
Wrapping these files would only make the problem worse as far as I can tell - as you wold be completely unable to merge changes.
While you can merge project files in some cases, it's not something that you should
count on being able to do. The basic recommendation is to avoid editing the project files at the same time as someone else.
I like versionning projects files (like the ones for Eclipse), only if I know they are:
not modified that often (certainly not by each developers)
only using relative paths
no data specifics to one workstation
In short, if those files are not to be merged (or will only be trivial to merge), I want them in a VCS. In your case, that may not be so useful to have them in said VCS in the first place.
Note: as mentioned in the Git manual:
During the merge, the index holds three versions of each file. Each of these three "file stages" represents a different version of the file:
$ git show :1:file.txt # the file in a common ancestor of both branches
$ git show :2:file.txt # the version from HEAD.
$ git show :3:file.txt # the version from MERGE_HEAD

Resources