1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-14 02:08:27 +08:00

Merge topic 'xcode-build-workspace'

844d79916a cmake --build: Add support for driving Xcode workspaces

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !10855
This commit is contained in:
Brad King
2025-06-11 14:26:33 +00:00
committed by Kitware Robot
8 changed files with 105 additions and 8 deletions

View File

@@ -736,6 +736,19 @@ following options:
Run :option:`cmake --build` with no options for quick help.
Generator-Specific Build Tool Behavior
--------------------------------------
``cmake --build`` has special behavior with some generators:
:generator:`Xcode`
.. versionadded:: 4.1
If a third-party tool has written a ``.xcworkspace`` next to
the CMake-generated ``.xcodeproj``, ``cmake --build`` drives
the build through the workspace instead.
Install a Project
=================

View File

@@ -0,0 +1,7 @@
xcode-build-workspace
---------------------
* The :ref:`cmake --build <Build Tool Mode>` command-line tool, when used
with the :generator:`Xcode` generator, now detects when a third-party
tool has wrapped the generated ``.xcodeproj`` in a ``.xcworkspace``,
and drives the build through the workspace instead.

View File

@@ -14,6 +14,7 @@
#include <cm/memory>
#include <cm/optional>
#include <cm/string_view>
#include <cmext/algorithm>
#include <cmext/string_view>
@@ -294,6 +295,40 @@ bool cmGlobalXCodeGenerator::FindMakeProgram(cmMakefile* mf)
return true;
}
std::string cmGlobalXCodeGenerator::GetAppleSpecificPlatformName()
{
std::string sdkRoot =
this->GetCMakeInstance()->GetState()->GetCacheEntryValue(
"CMAKE_OSX_SYSROOT");
sdkRoot = cmSystemTools::LowerCase(sdkRoot);
struct SdkDatabaseEntry
{
cm::string_view Name;
cm::string_view AppleName;
};
std::array<SdkDatabaseEntry, 6> const sdkDatabase{ {
{ "appletvos"_s, "tvOS"_s },
{ "appletvsimulator"_s, "tvOS Simulator"_s },
{ "iphoneos"_s, "iOS"_s },
{ "iphonesimulator"_s, "iOS Simulator"_s },
{ "watchos"_s, "watchOS"_s },
{ "watchsimulator"_s, "watchOS Simulator"_s },
} };
cm::string_view platformName = "MacOS"_s;
for (SdkDatabaseEntry const& entry : sdkDatabase) {
if (cmHasPrefix(sdkRoot, entry.Name) ||
sdkRoot.find(cmStrCat('/', entry.Name)) != std::string::npos) {
platformName = entry.AppleName;
break;
}
}
return std::string(platformName);
}
std::string const& cmGlobalXCodeGenerator::GetXcodeBuildCommand()
{
if (!this->XcodeBuildCommandInitialized) {
@@ -473,10 +508,15 @@ bool cmGlobalXCodeGenerator::Open(std::string const& bindir,
bool ret = false;
#ifdef HAVE_APPLICATION_SERVICES
std::string url = cmStrCat(bindir, '/', projectName, ".xcodeproj");
// If an external tool created a workspace then open it instead.
std::string url = cmStrCat(bindir, '/', projectName, ".xcworkspace");
bool const isWorkspace = cmSystemTools::FileIsDirectory(url);
if (!isWorkspace) {
url = cmStrCat(bindir, '/', projectName, ".xcodeproj");
}
if (dryRun) {
return cmSystemTools::FileExists(url, false);
return cmSystemTools::FileIsDirectory(url);
}
CFStringRef cfStr = CFStringCreateWithCString(
@@ -508,33 +548,47 @@ cmGlobalXCodeGenerator::GenerateBuildCommand(
int jobs, bool /*verbose*/, cmBuildOptions const& /*buildOptions*/,
std::vector<std::string> const& makeOptions)
{
// If an external tool created a workspace then build it instead.
std::string projectPath = cmStrCat(projectName, ".xcworkspace");
bool const isWorkspace = cmSystemTools::FileIsDirectory(projectPath);
if (!isWorkspace) {
projectPath = cmStrCat(projectName, ".xcodeproj");
}
std::string const targetFlag = isWorkspace ? "-scheme" : "-target";
std::string const projectFlag = isWorkspace ? "-workspace" : "-project";
GeneratedMakeCommand makeCommand;
// now build the test
makeCommand.Add(
this->SelectMakeProgram(makeProgram, this->GetXcodeBuildCommand()));
if (!projectName.empty()) {
makeCommand.Add("-project");
std::string projectArg = cmStrCat(projectName, ".xcodeproj");
makeCommand.Add(projectArg);
makeCommand.Add(projectFlag, projectPath);
}
if (cm::contains(targetNames, "clean")) {
makeCommand.Add("clean");
makeCommand.Add("-target", "ALL_BUILD");
makeCommand.Add(targetFlag, "ALL_BUILD");
} else {
makeCommand.Add("build");
if (targetNames.empty() ||
((targetNames.size() == 1) && targetNames.front().empty())) {
makeCommand.Add("-target", "ALL_BUILD");
makeCommand.Add(targetFlag, "ALL_BUILD");
} else {
for (auto const& tname : targetNames) {
if (!tname.empty()) {
makeCommand.Add("-target", tname);
makeCommand.Add(targetFlag, tname);
}
}
}
}
if (isWorkspace) {
makeCommand.Add(
"-destination",
cmStrCat("generic/platform=", this->GetAppleSpecificPlatformName()));
}
if ((this->XcodeBuildSystem >= BuildSystem::Twelve) ||
(jobs != cmake::NO_BUILD_PARALLEL_LEVEL)) {
makeCommand.Add("-parallelizeTargets");

View File

@@ -334,6 +334,7 @@ protected:
BuildSystem XcodeBuildSystem = BuildSystem::One;
private:
std::string GetAppleSpecificPlatformName();
std::string const& GetXcodeBuildCommand();
std::string FindXcodeBuildCommand();
std::string XcodeBuildCommand;

View File

@@ -178,4 +178,13 @@ endfunction()
BundleLinkBundle()
if(XCODE_VERSION VERSION_GREATER_EQUAL 12)
block()
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeWorkspace-build)
run_cmake(XcodeWorkspace)
set(RunCMake_TEST_NO_CLEAN 1)
run_cmake_command(XcodeWorkspace-build ${CMAKE_COMMAND} --build . --config Debug)
endblock()
endif()
# Please add device-specific tests to '../XcodeProject-Device/RunCMakeTest.cmake'.

View File

@@ -0,0 +1 @@
xcodebuild -workspace XcodeWorkspace\.xcworkspace build -scheme ALL_BUILD -destination generic/platform=MacOS

View File

@@ -0,0 +1,8 @@
enable_language(C)
add_executable(main main.c)
file(WRITE "${CMAKE_BINARY_DIR}/XcodeWorkspace.xcworkspace/contents.xcworkspacedata" [[
<?xml version="1.0" encoding="UTF-8"?>
<Workspace version = "1.0">
<FileRef location = "container:XcodeWorkspace.xcodeproj"/>
</Workspace>
]])

View File

@@ -0,0 +1,4 @@
int main(void)
{
return 0;
}