diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp index 201e1ccca10..11d82aeae40 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp @@ -156,8 +156,19 @@ QVariant CMakeTargetNode::data(Utils::Id role) const return m_artifact.fileName(); } - if (role == Ios::Constants::IosBuildDir) - return {}; // defaults to build configuration build directory + if (role == Ios::Constants::IosBuildDir) { + // This is a path relative to root build directory. + // When generating Xcode project, CMake may put here a "${EFFECTIVE_PLATFORM_NAME}" macro, + // which is expanded by Xcode at build time. + // To get an actual executable path, iOS plugin replaces this macro with either "-iphoneos" + // or "-iphonesimulator" depending on the device type (which is unavailable here). + + // dir/target.app/target -> dir + return m_artifact.parentDir().parentDir().toString(); + } + + if (role == Ios::Constants::IosCmakeGenerator) + return value("CMAKE_GENERATOR"); QTC_ASSERT(false, qDebug() << "Unknown role" << role.toString()); // Better guess than "not present". diff --git a/src/plugins/ios/iosconstants.h b/src/plugins/ios/iosconstants.h index 4e26e294606..7f4264ae3cc 100644 --- a/src/plugins/ios/iosconstants.h +++ b/src/plugins/ios/iosconstants.h @@ -47,6 +47,7 @@ const char IOS_DEPLOY_STEP_ID[] = "Qt4ProjectManager.IosDeployStep"; const char IosTarget[] = "IosTarget"; // QString const char IosBuildDir[] = "IosBuildDir"; // QString +const char IosCmakeGenerator[] = "IosCmakeGenerator"; const quint16 IOS_DEVICE_PORT_START = 30000; const quint16 IOS_DEVICE_PORT_END = 31000; diff --git a/src/plugins/ios/iosrunconfiguration.cpp b/src/plugins/ios/iosrunconfiguration.cpp index aa3abc7b765..1198644a3ac 100644 --- a/src/plugins/ios/iosrunconfiguration.cpp +++ b/src/plugins/ios/iosrunconfiguration.cpp @@ -169,30 +169,85 @@ FilePath IosRunConfiguration::bundleDirectory() const return {}; } FilePath res; + bool shouldAppendBuildTypeAndPlatform = true; if (BuildConfiguration *bc = target()->activeBuildConfiguration()) { Project *project = target()->project(); - if (ProjectNode *node = project->findNodeForBuildKey(buildKey())) - res = FilePath::fromString(node->data(Constants::IosBuildDir).toString()); - if (res.isEmpty()) + if (ProjectNode *node = project->findNodeForBuildKey(buildKey())) { + QString pathStr = node->data(Constants::IosBuildDir).toString(); + const QString cmakeGenerator = node->data(Constants::IosCmakeGenerator).toString(); + + if (cmakeGenerator.isEmpty()) { + // qmake node gives absolute IosBuildDir + res = FilePath::fromString(pathStr); + } else { + // CMake node gives IosBuildDir relative to root build directory + + bool useCmakePath = true; + + if (pathStr.isEmpty()) + useCmakePath = false; + + if (useCmakePath && cmakeGenerator == "Xcode") { + // When generating Xcode project, CMake may put a "${EFFECTIVE_PLATFORM_NAME}" macro, + // which is expanded by Xcode at build time. + // To get an actual executable path at configure time, replace this macro here + // depending on the device type. + + const QString before = "${EFFECTIVE_PLATFORM_NAME}"; + + int idx = pathStr.indexOf(before); + + if (idx == -1) { + useCmakePath = false; + } else { + QString after; + if (isDevice) + after = "-iphoneos"; + else + after = "-iphonesimulator"; + + pathStr.replace(idx, before.length(), after); + } + } + + if (useCmakePath) { + // With Ninja generator IosBuildDir may be just "." when executable is in the root directory, + // so use canonical path to ensure that redundand dot is removed. + res = bc->buildDirectory().pathAppended(pathStr).canonicalPath(); + // All done with path provided by CMake + shouldAppendBuildTypeAndPlatform = false; + } else { + res = bc->buildDirectory(); + } + } + } + + if (res.isEmpty()) { + // Fallback res = bc->buildDirectory(); - switch (bc->buildType()) { - case BuildConfiguration::Debug : - case BuildConfiguration::Unknown : - if (isDevice) - res = res / "Debug-iphoneos"; - else - res = res.pathAppended("Debug-iphonesimulator"); - break; - case BuildConfiguration::Profile : - case BuildConfiguration::Release : - if (isDevice) - res = res.pathAppended("Release-iphoneos"); - else - res = res.pathAppended("Release-iphonesimulator"); - break; - default: - qCWarning(iosLog) << "IosBuildStep had an unknown buildType " - << target()->activeBuildConfiguration()->buildType(); + shouldAppendBuildTypeAndPlatform = true; + } + + if (shouldAppendBuildTypeAndPlatform) { + switch (bc->buildType()) { + case BuildConfiguration::Debug : + case BuildConfiguration::Unknown : + if (isDevice) + res = res / "Debug-iphoneos"; + else + res = res.pathAppended("Debug-iphonesimulator"); + break; + case BuildConfiguration::Profile : + case BuildConfiguration::Release : + if (isDevice) + res = res.pathAppended("Release-iphoneos"); + else + res = res.pathAppended("Release-iphonesimulator"); + break; + default: + qCWarning(iosLog) << "IosBuildStep had an unknown buildType " + << target()->activeBuildConfiguration()->buildType(); + } } } return res.pathAppended(applicationName() + ".app"); diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp index b3b719f9257..1214b79d64d 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp +++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp @@ -409,6 +409,11 @@ QVariant QmakeProFileNode::data(Utils::Id role) const return info.buildDir.toString(); } + if (role == Ios::Constants::IosCmakeGenerator) { + // qmake is not CMake, so return empty value + return {}; + } + if (role == ProjectExplorer::Constants::QT_KEYWORDS_ENABLED) return !proFile()->variableValue(Variable::Config).contains("no_keywords");