Can you change per-file options for a group of files? - xcode

I have a nested group of dozens of files (as described in this question), and I'd like to apply some custom build settings to all and only those files.
This was trivial in Xcode 3.
In Xcode 4, although I couldn't find anything in the documentation, I found a workaround: if you can select all of the files you want to change in the Compile Sources list (which happens to work for me because all of the files in my group have the same namespace prefix, and only one other file in the project shares it, so I can search for the prefix, select all, then deselect the one extra file), then hit Return, it will pop up the compile settings dialog for all selected files. (Double-clicking, context menu, etc. doesn't work, only Return.) (From a quick search, I found the same workaround discussed in this question.)
In Xcode 5 and 6, that workaround no longer works; selecting the files and hitting Return (or Fn+Enter, or double-clicking, or right-clicking or anything else I can think of) has no effect.
I've tried using AppleScripting to do this, but, as with my previous problem, I can't get past the fact that any attempt to access the build files of a build phase object returns a generic -10000 error… So, unless there's actually a solution, it looks like I'll be writing a script to parse the pbxproj as a plist again, which I'd really like to avoid.

As of Xcode 6.1, Yes
I just tested this in Compile Sources in Xcode 6.1, and I can
custom select on a search
edit the compile settings for the selected files
But if not...
Your last line was about writing a parser for pbxproj, I thought I would recommend Ruby-based tool for that, Xcodeproj. In their own words,
Create and modify Xcode projects from Ruby.
It is an integral part of CocoaPods, and therefore very actively used and maintained.

Related

$(shell some-command) equivalent for Visual Studio project macros?

With Makefiles I'm used to being able to write things like:
includedir=$(shell pg_config --includedir)/server
to run an external program, pg_config, with argument(s) --includedir, and include the result in a variable or as part of a variable. So if pg_config --includedir output /usr/include to stdout, the value of includedir would become:
includedir=/usr/include/server
Is there any way to do the equivalent with a Visual Studio project? Run a command, get the result, and substitute it into a property?
I find myself having to edit properties pages all over the place - changing the include directories and library directories for both the x86 and x64 configurations of a project whenever I want to build an extension against a different PostgreSQL version. It is intensely frustrating.
I want to be able to put something like this into Configuration Properties -> C/C++ -> General -> Additional Include Directories:
%(shell pg_config --includedir)
or even better:
%(shell %(PG_CONFIG) --includedir)
where %(PG_CONFIG)'s location is defined in a single place for each platform in the project.
So I'm looking for at least user-defined macros, and preferably the ability to invoke a command line tool and replace the macro with the resulting standard output.
(Preferably in a way that doesn't involve delving into semi-documented UI elements that move and get renamed in every VS version, and that appear and disappear from the various Express editions).
This has been possible in Makefiles for 20 years, there must be a way to do it in VS, right? Or do "Real Windows Developers" generate their VS projects with scripts and build them using MSBuild?
I've looked at some similar questions without finding much of use, e.g.:
Visual Studio - Where to define custom path macros?
In particular, I'm aware of property sheets (View -> Other Windows -> Property Manager), but they don't seem to provide a way to set a value in just one place, they're still per-configuration and per-architecture, so if you have four configurations and two architectures it gets awkward. Unlike with the normal project property editor you can't even apply a change across a group of architectures/configurations, either.
I could use a VS extension, but they require installation into the user's VS, can be version-specific, and seem like a very big hammer for a small problem.
I find myself having to edit properties pages all over the place
That bugged me to no end as well. Property sheets to the rescue! When setting up a major solution in VS10, for example, I had every project pull in a settings.props that contained the common settings, made in only one place. Then go through all the generated or imported projects and kill any explicit value (even if blank) for everything possible. That way things will inherit from property sheets. Select "all configurations" and on each properly use the drop-down to "inherit from...".
I have property sheets for each special library too, just defining the proper #define, include paths, lib paths, etc. Projects that use that particular external lib simply use that property sheet. Users are told, in the worst case, to “edit the XML to change the path to where you have Boost”.
As for setting such a properly to a dynamic determined value, you can do that too. There are property functions you can use.
It sounds like you're going down the same path as I did.
More notes: “prop sheets are per configuration/platform”: If you include a prop sheet at the top-level node for the project itself (not the Debug|Win32, etc. child nodes) it will include it into all current configurations at once. If you edit the properly page, you can choose Multiple or All configurations on the Property dialog box, just as with the usual project use of the Property dialog.
“Custom user macros are well hidden” A property page shows up for that when in a property sheet you created, but not when opening property dialog on a proj file as in the normal File View. The macro will be set in one place (the prop page) and usable as a $(name) in all projects that include it, and even in other property pages that come later in the evaluation sequence.
Let me know how it goes. You should be able to do everything you asked.
—John
In addition to #jdlugosz's answer:
It looks like the traditional way to do this with Visual Studio, before the advent of property functions, was to write a new MSBuild Task. The task can potentially do things like modify a property sheet.
MSBuild supports "inline tasks" where the task code is in the MSBuild project file, rather than a separate assembly, so it might not be neccessary to create a new subproject just for the task.
There are a bunch of built-in tasks, like Exec and CreateProperty that may be useful.
The docs say that:
[The Exec task] is useful when a specific MSBuild task for the job that you want to perform is not available. However, the Exec task, unlike a more specific task, cannot gather output from the tool or command that it runs.
... but that seems to be outdated/wrong so you don't need horrible workarounds.
So, prior to .NET 4.5 I'd probably have to write a custom task for this simple job, because there's no way to feed the command stdout/stderr into the CreateProperty task or have Exec create a property directly. But in 4.5 it looks like I can do it directly. At least in VS Express support for tasks etc is very limited so you'll probably land up editing the XML.

Unlock Xcode Project File for Find and Replace

I make common use of Xcode's workspace Find and Replace. It's very powerful when combined with regex.
However, I've got a workspace with 30-40 projects and a large change to the build settings has just been required. I expected to hop into Xcode, and put some regex to use to change the build setting for all projects when I was hit with a block. All my Xcode project files are locked. So the regex find works great, but I have no way of replacing. I can't even preview it. It is only affecting project files that I can see. I opened Finder to check permissions and they are wide open and the OSX file lock is off on all of them. So this seems to be an Xcode locking issue. I tried to lock/unlock the project files the way you would a normal file (File > Unlock...) in Xcode but these options are grayed out for projects.
Anyone encounter this before? Any possible solutions before I have to hand update build settings for 30+ projects?
I did some more digging on this question to confirm or refute my hypothesis from the comments above. Xcode does indeed work directly against the on-disk data for the files involved in find/replace activities. Filesystem events suggest that the find/replace operation opens the .pbxproj file and begins regex activities from top to bottom working through the file and group references to the build configurations and settings sections ultimately applying the search to the on-disk data pointed to by each of the entries in the .pbxproj
Naturally, depending on the regex the user enters, it would be entirely possible to match content exactly at the cursor's current location in the search and trigger a replacement operation that would destroy the current search's context. This would have the most likely effect of terminating the search prematurely, but could also trigger an infinitely long find/replace operation (ex. find '.' replace with 'aa') if the search wasn't well contained. To stem off the entire class of 'self eating snake' problems when it comes to this Xcode find/replace behavior, it seems that Apple has elected to lock the .pbxproj for the duration of the search operation. While this does mean that you can't use Xcode's Find/Replace regex tools, there are a number of great text editors out there (even free ones!) that allow you to do regex find/replace via a Multi-file search (TextWrangler and BBEdit). These editors allow you to filter your search to a file pattern (say *.pbxproj) in subfolders of your master project. Depending on how your projects are organized on disk, pick a search starting at a common ancestor and you can walk your way through the find/replace operation just as you would in Xcode. In fact, the same regex strings you identified in Xcode can be used in these tools to affect the change(s) you need.
As with most massive or autonomous edits, make sure you keep backups of the files you intend to edit (this goes at least doubly so for you since your projects are entirely local, non-source controlled projects) just in case you need to rollback your changes. Good luck and let us know which avenue you wound up taking and how things went.

Force Xcode to update project files

OK, here's my issue :
I'm using Xcode 4.6 under Lion
In my current project I've added several "real" folders (either with sources or with resources) which Xcode represents as "Groups"
However, whenever I add another file in one of my already-imported folders, the file doesn't show up (but instead I have to manually drag each new file to its appropriate location).
Well, given that my project is comprised of hundreds of different files, and that files are being added constantly, this seems like an overkill.
I realize this may have to do with Xcode's Group-centric approach, but it still bothers me.
So, is there any workaround? Any ideas?
As for many IDE, it won't scan changes of new files in included folder, to prevent accidental add of extra codes that will break the compile process. If you really want to do so, write a script to add all files in the folder and run it at pre-compile stage, i.e. in Xcode, "External Target"
See: https://stackoverflow.com/a/976459/188331

Xcode -- groups and targets

I have an Xcode project. The project currently has four targets, and I am about to add more. Within the project are about 150 png files. I have all of these in a tree of groups in the Xcode "groups and files" panel.
I want to include these png files in some of my targets, but not in others. The thing is, I will always want either all of them or none of them. I don't want to pick and choose.
Is there a way to manage this? Basically, I want some targets to use all of the files in the "png files" group, and others to use none of them. If there is a way to include an entire tree of groups in a target, and remove the same tree from another target, without having to do each file individually, that would be ideal.
EDIT: starting a bounty on this due to the lack of response. If it's not possible to do the above, I would be interested in other ways to accomplish more or less the same thing -- for example would it help to make all the png files a shared library? Or to make them a target in and of themselves, and have some of my other targets depend on that one? In either case, I would need to know how to set the thing up.
My bottom line is that I want to do the whole thing as simply as possible. For example, it should be easy to add a file to the 150 and tell my project that it should be included in all targets that use that group of files.
I am using the Xcode 3.2.3 right now. I am able to right click on a group, select get info then jump over to the 'Targets' tab and select my targets I want those files to go into. It works for me, is this what you are looking for?
Write a script and include it in the appropriate targets as Run Script Phases. Since it gets environment variables from Xcode it’s pretty easy for the script to copy files over to the right place. You can also pass more information to the script and maintain a clean, code-only Xcode project.
You’ll have a directory full of images, and every time the script runs (as you build the targets) it copies everything. To add an image, you add it to the directory without modifying the Xcode project.

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.

Resources