Someone jump in and correct me if I’m wrong, but I believe there are many reasons that Apple sticks with a hand-maintained Xcode project. I will try to summarize some of the reasons here:
-
People are more comfortable editing a native solution file than editing CMake. I certainly sympathize with this, as I also strongly prefer editing a Visual Studio solution over a CMake file. Before working on LLDB, I had actually never even written a line of CMake before.
-
The Xcode projects generated by CMake are slow, almost to the point of being unusable. This is a widespread problem with IDEs, and indeed the MSVC generator suffers from the same problem. The issue here is related to the size of the project / solutions. Every CMake target (which ultimately translates to a static library or shared library) ends up as a project in your solution (MSVC) or target in your project (Xcode). This is the layer at which dependency analysis is performed and build parallelization is implemented, so having more projects causes tremendous slowdown in loading projects/solutions and generating information for intellisense/code completion. Visual Studio has gotten much better in this regard with recent versions, but it’s still an issue. And I think Xcode has not gotten much better in this regard. In short, an Xcode generated solution, while it will technically work, is almost unusable for performance reasons.
-
The Xcode projects generated by CMake aren’t as pretty as hand-generated Xcode projects. It’s actually possible to make prettier generated projects by adding some stuff to the CMake, but right now they just don’t look as nice.
-
Legacy reasons (aka old habits die hard). The LLDB group at Apple has historically treated LLVM and clang as libraries, and in the past the only supported way to build LLDB was against a known revision of clang and LLVM, and only recently (well, not recent anymore, but legacy decisions can have long lasting implications) was it changed so that LLDB is expected to always build against tip of trunk LLVM / clang. One of the things that came out of this early separation was that an Xcode build of LLDB does not even use the canonical on-disk directory hierarchy that all other LLVM subprojects use. A normal LLVM directory layout looks like this:
llvm
– tools
---- lldb
---- clang
---- lld
Since LLDB considers itself “not an LLVM subproject, but rather a standalone project which uses LLVM”, it organizes itself like this:
lldb
– llvm
---- tools
------ clang
------ lld
Of course, this is just an implementation detail, as we’ve shown that lldb can be built as a normal subproject on all other platforms using the first layout, but this basically boils down to “old habits die hard”. It’s what people are used to.
It’s certainly easy to sympathize with numbers 1, 3, and 4 but ultimately I think (or at least hope) that people would be willing to sacrifice these for the greater good of having a unified build system. Number 2 however, is probably a showstopper though.
I’m not sure just how bad the Xcode solution is in terms of performance, but it’s the primary reason why the the standalone build exists. The standalone build generates a much smaller project/solution, with only those projects and targets that are part of LLDB itself, and not projects from LLVM, clang, etc. It attempts to use an installed LLVM / clang instead of building one.
One thing that has worked very well for me on Windows is using my IDE for editing and debugging, but not for building. There’s quite a lot to like about this approach. For starters, the performance of building from inside the IDE is irrelevant now, because you’re not building from the IDE anymore. For Visual Studio this makes a huge difference, but I’m not sure if it makes a difference for Xcode. Another advantage of this approach is that honestly, ninja is just faster than everything else. It really is. And not a little bit, but a lot. I’m a big fan of my IDE and you will only pry it out of my cold dead hands, but after I tried ninja once or twice, it was obvious that it was a huge win over building from the IDE. All it takes me is typing “ninja” from a command shell. Even I can manage that. Everything else - debugging, code completion, editing experience, file browsing - still works. I just don’t hit build from inside the IDE.
It would be worth seeing if an approach like this would work well with people from Apple. Or alternatively, maybe seeing if the Xcode IDE team within apple would be willing to prioritize IDE performance in the case of these larger projects. Visual Studio seems to have come a long way here, so it doesn’t seem impossible for Xcode to improve here, it just has some work to do.