Simultaneous Xcode command-line builds with different Xcode-select values - xcode

Our build server has multiple versions of Xcode installed. Our build scripts use xcode-select to choose the correct version. All that is fine.
Some of our builds take a while to run. We're thinking of allowing multiple simultaneous builds (Bamboo agents) on the same build server. My worry is that xcode-select on different (but simultaneous) builds would cause a race condition. A build that begins with Xcode 9.4.1 might get switched to Xcode 10.0 mid-build if a second build begins and requires that version.
My only thoughts are to use VM's/new machines to parallelize the builds.
I'm curious if anyone's dealt with this scenario. Thanks.

You might try using xcrun instead of xcode-select to invoke your xcodebuilds. You may find your builds contending for system resources when building concurrently...

You can set the DEVELOPER_DIR environment variable rather than switching the active Xcode using xcode-select.
From the xcode-select man page:
ENVIRONMENT
    DEVELOPER_DIR
        Overrides the active developer directory. When DEVELOPER_DIR is set, its value will be used instead of the system-wide active
developer directory.
        Note that for historical reason, the developer directory is considered to be the Developer content directory inside the Xcode
application (for example
/Applications/Xcode.app/Contents/Developer). You can set the environment variable to either the actual Developer contents
directory, or the Xcode application directory -- the
xcode-select provided shims will automatically convert the
environment variable into the full Developer content path.

Related

TeamCity unmet requirement: MSBuildTools12.0_x86_Path exists (Mac only)

I've seen this question asked but never specifically for Mac. My company is using TeamCity on a Mac Mini to do our iOS and android builds. We would use windows but, iOS builds require a Mac with Xcode. I have not been able to satisfy this condition. I can see that there are multiple versions of MSBuild (and Xbuild) already on my machine. Here is what I tried:
set an environment variable for MSBuildTools12.0_x86_Path using launchctl setenv (tried the bin directory of every instance of MSBuild existing on my machine), rebooted before checking TC
setting env.MSBuildTools12.0_x86_Path entry in buildAgent.properties
setting system.MSBuildTools12.0_x86_Path entry in buildAgent.properties
logging into TeamCity, going to my build configuration, going to the "parameters" tab and adding a new parameter for env.MSBuildTools12.0_x86_Path
After all of the above failed to satisfy the condition, I tried grabbing version 12 of MSBuild from a Windows machine, copying it to my Mac and pointing to its "Bin" directory instead, and repeating all bullets above.
The path was /Users/myusername/MSBuild/12.0/Bin. This bin directory contains MSBuild.exe, an MSBuild folder, a bunch of DLLs and more.
Again, this failed to change the outcome of the unmet condition in TeamCity. The frustrating thing is that TeamCity isn't giving me details. I don't know if it's still complaining that the path isn't even set (and where it is even looking for that path definition), or if it SEES that the path is set but it's not pointing to a folder it recognizes as MSBuild. I'm completely in the dark.
Does anyone have any guidance for me on this? I feel I've exhausted all paths to a solution. Thank you so much, in advance.
I figured it out on my own. On the Mac, you have to do an "MSBuild" runner type and pick "Mono xbuild 4.5" for the version. I used "x86" for the run platform and set a parameter for Mono4.5_x86 to point to xbuild. But it was trying to run the 64 bit version of mono and I found no way to set a command line argument for mono to tell it I want --arch=32 so I ended up having to link the mono executable to mono-sgen32 to get the build to finally work.

Does DEVELOPER_DIR need to remain set in the environment?

I'd like to have side-by-side installations of XCode, and use the DEVELOPER_DIR environment variable to select between them. The goal for this is to use the result of xcrun -f --sdk macosx clang to determine the appropriate C compiler, and then use that in a script or build system.
CC=$(DEVELOPER_DIR=<something> xcrun -f --sdk macosx clang)
My question is whether DEVELOPER_DIR needs to remain set when using the tools found by xcrun, or whether it is OK to just set it during the execution of xcrun, as is done above, and then use the returned tools in the default environment, without DEVELOPER_DIR still set.
In other words, while xcrun clearly does depend on the value of DEVELOPER_DIR, do the tools themselves depend on it too? Is there a meaningful difference between:
DEVELOPER_DIR=<whatever> command CC=$(xcrun -f --sdk macosx clang)
command CC=$(DEVELOPER_DIR=<whatever> xcrun -f --sdk macosx clang)
Is the second one correct? Or only the first?
I'd like to have side-by-side installations of XCode, and use the DEVELOPER_DIR environment variable to select between them.
It's fine to have two or more versions of Xcode installed. The usual way to select between them is to use the xcode-select command, but the man page for that command does seem to say that you can accomplish the same thing for just the current session by setting the DEVELOPER_DIR environment variable yourself. Here's what the documentation for the --switch option says:
Sets the active developer directory to the given path, for example
/Applications/Xcode-DP.app. This command must be run with superuser
permissions (see sudo(8)), and will affect all users on the system. To
set the path with-out superuser permissions or only for the current
shell session, use the DEVELOPER_DIR environment variable instead
(see ENVIRONMENT).
However, you should also heed the advice given in the ENVIRONMENT section:
Note that for historical reason, the developer directory is considered
to be the Developer content directory inside the Xcode application
(for example /Applications/Xcode.app/Contents/Developer). You can set
the environment variable to either the actual Developer contents
directory, or the Xcode application directory -- the code-select
provided shims will automatically convert the environment variable
into the full Developer content path.
So the <whatever> in your question should specify the full path to the Developer directory, not just to the Xcode application.
In other words, while xcrun clearly does depend on the value of DEVELOPER_DIR, do the tools themselves depend on it too? Is there a meaningful difference between:
• DEVELOPER_DIR=<whatever> command CC=$(xcrun -f --sdk macosx clang)
Using xcrun to find the tools so that you can invoke them yourself and worrying about when to set and unset DEVELOPER_DIR seems overly complicated. Per the xcode-select documentation, all the "shims" respect the DEVELOPER_DIR setting. "Shims" here refers to the Xcode commands in /usr/bin. As long as that environment variable is set correctly, you can just invoke '/usr/bin/clang' instead of whatever xcrun finds, and /usr/bin/clang will call through to the clang version in DEVELOPER_DIR. Presumably, you're asking this question because you're writing a build script of some kind, so there should be no problem setting DEVELOPER_DIR early in that script and then just using the /usr/bin commands.
• command CC=$(DEVELOPER_DIR=<whatever> xcrun -f --sdk macosx clang)
Programs inherit the environment from their parent processes. Here you're finding the right copy of clang to use, but you'll invoke it in an environment where DEVELOPER_DIR isn't set. Whether this matters depends on whether the tool you're using invokes any other tools. I honestly don't know whether any of the tools do invoke other tools, but it seems logical that a tool like xcodebuild would invoke many of those tools and therefore depend on DEVELOPER_DIR being set correctly.
In short, there's no downside to setting DEVELOPER_DIR as needed in your build script, and trying to specify it only in your call to xcrun seems less reliable in general than the alternative approach.

Configuring Xcode project to be built with specific build tools version

In my build system, I am using xcodebuild to build multiple projects.
I want to configure different Xcode installation to be used per project.
I know about sudo xcode-select --switch <path>, but:
This option is system-wide, and might mess up with other parallel
builds.
It requires root, which I prefer to avoid (since it's an automatic build system).
It is not configured internally in the project.
Is there a way to specify the build tools path to use per project?
From the output of xcrun:
The active developer directory can be set using xcode-select, or via the DEVELOPER_DIR environment variable. See the xcrun and xcode-select manual
pages for more information.
E.g. to run xcodebuild with a specific Xcode-installation:
$ DEVELOPER_DIR=/path/to/my/Xcode.app/Contents/Developer xcodebuild
In a bash script:
export DEVELOPER_DIR=/path/to/my/Xcode.app/Contents/Developer
xcodebuild
You can probably launch xcodebuild directly from Applications/Xcode.app/Contents/Developer/usr/bin, so modifying the path you will use different Xcode version.

LLDB: Must I build it from source (XCode project) to use it from the command line?

XCode comes with LLDB, presumably there is a way to enable it as the debugger to use when debugging XCode projects.
Of course being a Linux user I have become a hardcore command-line fanatic and I have a well-established Vim and Tmux workflow. Also being a code portability freak, 100% of my scripts work on both OS X and Linux.
So is there some sort of way to "Pull out" the LLDB from deep within the bowels of XCode and run it from the command line? What are the benefits of compiling it ourselves, as directed from the instructions?
I am guessing that the usual reasons to build from source apply here as well: We can get the latest bleeding edge features and bugfixes by rebuilding it. It's just better. etc. How can I check which version of clang a particular LLDB instance uses? I did compile it using the XCode project (by following those directions), and version reports:
steven#new-host-3:~/Library/Developer/Xcode/DerivedData/lldb-bvjmzslapfdmdmabqocfcogrlbfc/Build/Products/Debug Wed 3 20:37 10137
% ./lldb
(lldb) version
lldb-300.99.0
The answer won't directly help me since I already know how to build the entire thing from source, but for everyone else out there with a Mac who is thinking about ditching GDB (and actually intends to do debugging out of a command line), maybe there's a shortcut (that I skipped)!
I guess there still is a significant difference between this bleeding edge svn-sourced manually compiled LLDB and the LLDB that Apple packages with XCode and XCode CLT.
The convention on Mac OS X with Xcode 4.6 is that you either install the CommandLineTools package (which installs things in /usr/bin etc) or you prefix commands with xcrun. xcrun lldb, xcrun clang, etc. Most users of Xcode do not use command line tools so this arrangement works well. I believe you can download the CommandLineTools package alone if you're only doing command line development from http://developer.apple.com/ (I think an Apple ID is required to get access -- I think a free account will be sufficient to get the CommandLineTools package) which means you can get the full command line tools with a single 128MB download.
The change to have the canonical home for everything be in /Applications/Xcode.app is a relatively new one and the goal that drove this change was to make the developer tools relocatable. It will install in /Applications/Xcode.app if you download it from the Mac App Store, but it doesn't need to be there. You can install multiple versions of the tools on a single system - for instance, people who have access to the Xcode 5 Developer Previews will see that it installs in a separate location so the Xcode 4.6 tools are still present on the system. The xcode-select command line program can be used to specify which set of Xcode.app tools should be invoked by xcrun clang etc.
As an aside, a useful shortcut for people more comfortable building from Terminal: if you are building lldb you can do xcodebuild -configuration Debug and it will build the Debug configuration for you, no Xcode UI required.
Maybe I took the scenic route here.
% /Applications/Xcode.app/Contents/Developer/usr/bin/lldb
(lldb) version
LLDB-179.6
(lldb)
This is probably useful enough to get work done with.
It's kind of unfortunate to see that the Xcode CLT and Xcode itself come with similar tools, it's a waste of disk space.
See the sister question here.

where is $PATH set in xcode?

It looks like xcode's $PATH environment setting is different from my user shell environment.
Where does xcode get the $PATH setting from and what's the best way to append to the search path?
if you're writing a Run Shell Script build phase, you can just do:
PATH=${PATH}:/opt/local/bin
or whatever inside the script content.
There's some confusion in these answers, as some of them are trying to solve the $PATH for the built executable being run by Xcode. But the question is about Xcode, implying that it's about the build process itself.
For example, in a Build Phase Run Script step that runs an executable installed by Homebrew. It's not a good idea to hard-code the build process to include a path that is specific to one build machine (New macOS versions come out, new developers join the team, etc.)
The problem has multiple layers:
Changing $PATH in bashrc/zshrc/profile takes effect on shell sessions, but not in macOS applications
To solve this, you can set the PATH for applications using:
sudo launchctl config user path $PATH
You will then need to restart your machine for the change to take effect. You will need to run this again if you change your $PATH.
(This came from a comment on GitHub.)
Xcode by default does not use the system $PATH, and replaces it with its own sanitized value
This is solved by changing a User Default. This probably has some risk, since Xcode does this sanitization to ensure that its own build tools are used, and if you have executables with the same name in other places, they might be run instead. Caveat emptor!
defaults write com.apple.dt.Xcode UseSanitizedBuildSystemEnvironment -bool NO
And it looks like this gets reset on every restart of macOS, so be prepared to issue this command every time you restart.
(This part came from this answer.)
The easiest solution is to add the PATH variable in Xcode.
PATH=${PATH}:/usr/local/bin
This applies for OSX 10.7 and earlier ONLY.
XCode gets its environment variables the same way as other OS X processes, from ~/.MacOSX/environment.plist.
Check developer.apple.com/qa/qa2001/qa1067.html for details on how to set things.
In Xcode 5 you can add your PATH as a variable to either a target or the project settings.
Add a custom variable with the +sign on the top of the page
Edit the name of the variable to be PATH and add your preferred value (e.g. /usr/local/bin for a default install of homebrew.
If you are talking specifically about the executable search path environment variable named PATH, then there are a few places that it is set:
In your shell settings if it is a command line tool. Depending on your shell, this could be ~/.cshrc, ~/.profile, ~/.bash_profile, etc.
In the environment.plist file that was mentioned earlier.
If you are in a debugger, then it is whatever gdb uses. I believe that gdb will read commands from ~/.gdbinit if it exists.
XCode lets you set environment variables within the Info page for executables.
This is an update for later versions of macOS and Xcode as things have altered. This is with Xcode 11.0 and macOS 10.14
The biggest issue is that ~/.MacOSX/environment.plist does not get read now.
Build Settings
This means that if in the build you need the PATH set, e.g. for external builds and they run executables there is no simple solution. /etc/paths does not seem to be read either.
The solution is as in #GhostLyrics answer to add the PATH variable in Build Settings. However as noted in comments Xcode will not just use that value but it puts its own values before that. Also it does a straight textual substitution and so you need to also add the separator that PATH uses i.e. the : (colon). The value I have added is :opt/local/bin I also found that you can only do this for a target and not at the project level.
Run Shell Script
This is the simple case as in this answer
PATH=${PATH}:/opt/local/bin
or whatever inside the script content.
Alternatively put this change in your non login shell starter file e.g. ~/.bashrc ~/.zshrc
Running the executable
This is done in the Schema in the Run portion.
Set PATH in the environment variables as stated in answers here. Note I have not tried this and I am not certain how much of the PATH needs setting.
Xcode doesn't look at your shell path environment.
Have a look at NSProcessInfo; and do an NSLog to see what comes up.
If you want a path to apply to all graphical programs you need to set up the ~/.MacOSX/environment.plist. as described.
The recommended way to set the environmen variables are actually in /etc/paths and etc/paths.d although these are also not picked up by Xcode.
I asked about this here.
Nothing was working for me in XCode 7.
You need to set the PATH variable in XCode schemes.
Found the solution at:
Where to set environment variables for app?
Try opening your xcode project from the terminal, this worked for me: open some.xcodeproj
Instead of opening xcode and then loading the project or double clicking on it.
I know... silly

Resources