diff options
author | Sheree Morphett <[email protected]> | 2025-07-08 09:14:02 +0300 |
---|---|---|
committer | Sheree Morphett <[email protected]> | 2025-10-13 11:29:58 +0000 |
commit | 039c794cc2a4b4a49a04ba3ff2b5959b896ca951 (patch) | |
tree | 1a5c32379f069681a47aaeb601880216457da1de | |
parent | a284e2cd66e2d45364203a249bb3ec7a52f939b5 (diff) |
Insert QT_ANDROID_SOURCE_PACKAGE_DIR on APK template creation
Inserts the QT_ANDROID_SOURCE_PACKAGE_DIR and chosen directory into the
CMakeLists.txt for the project when using APK templates.
Fixes: QTCREATORBUG-33360
Change-Id: If138a8bc9b296f1ccc2af76dadd77e7fcdfb3dca
Reviewed-by: Ville Voutilainen <[email protected]>
-rw-r--r-- | src/plugins/android/androidconstants.h | 1 | ||||
-rw-r--r-- | src/plugins/android/manifestwizard.cpp | 26 | ||||
-rw-r--r-- | src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp | 147 | ||||
-rw-r--r-- | src/plugins/cmakeprojectmanager/cmakebuildsystem.h | 15 | ||||
-rw-r--r-- | src/plugins/projectexplorer/buildsystem.cpp | 10 | ||||
-rw-r--r-- | src/plugins/projectexplorer/buildsystem.h | 3 |
6 files changed, 183 insertions, 19 deletions
diff --git a/src/plugins/android/androidconstants.h b/src/plugins/android/androidconstants.h index 7f787cd13cf..0ede9a08d4c 100644 --- a/src/plugins/android/androidconstants.h +++ b/src/plugins/android/androidconstants.h @@ -39,6 +39,7 @@ const char ANDROID_APPLICATION_ARGUMENTS[] = "ANDROID_APPLICATION_ARGUMENTS"; const char ANDROID_DEPLOYMENT_SETTINGS_FILE[] = "ANDROID_DEPLOYMENT_SETTINGS_FILE"; const char ANDROID_SO_LIBS_PATHS[] = "ANDROID_SO_LIBS_PATHS"; const char JAVA_HOME_ENV_VAR[] = "JAVA_HOME"; +const char QT_ANDROID_PACKAGE_SOURCE_DIR[] = "QT_ANDROID_PACKAGE_SOURCE_DIR"; const char ANDROID_RUNCONFIG_ID[] = "Qt4ProjectManager.AndroidRunConfiguration:"; const char ANDROID_PACKAGE_INSTALL_STEP_ID[] = "Qt4ProjectManager.AndroidPackageInstallationStep"; diff --git a/src/plugins/android/manifestwizard.cpp b/src/plugins/android/manifestwizard.cpp index aec8d009c2c..982993f045c 100644 --- a/src/plugins/android/manifestwizard.cpp +++ b/src/plugins/android/manifestwizard.cpp @@ -274,8 +274,7 @@ void CreateAndroidManifestWizard::createAndroidTemplateFiles() if (m_buildSystem->project()->type() != CMakeProjectManager::Constants::CMAKE_PROJECT_ID) node->addFiles(copy.files()); - QString androidPackageDir; - androidPackageDir = node->data(Android::Constants::AndroidPackageSourceDir).toString(); + QString androidPackageDir = node->data(Android::Constants::AndroidPackageSourceDir).toString(); if (androidPackageDir.isEmpty()) { const BuildTargetInfo bti = m_buildSystem->buildTarget(m_buildKey); const FilePath projectDir = bti.projectFilePath.parentDir(); @@ -290,13 +289,22 @@ void CreateAndroidManifestWizard::createAndroidTemplateFiles() ? QString(QLatin1String("QT_")) + Android::Constants::ANDROID_PACKAGE_SOURCE_DIR : QString(Android::Constants::ANDROID_PACKAGE_SOURCE_DIR); - QMessageBox::warning( - this, - Tr::tr("Project File Update Failed"), - Tr::tr( - "Could not automatically update the project file for \"%1\".\n" - "Set the %2 property manually.") - .arg(bti.projectFilePath.toUserOutput(), androidPackageSrcDir)); + const QString relativePath = m_directory + .relativePathFromDir( + m_buildSystem->buildTarget(m_buildKey).projectFilePath); + androidPackageDir = QString("${CMAKE_CURRENT_SOURCE_DIR}/%1").arg(relativePath); + + bool result = m_buildSystem->setTargetProperty(node, androidPackageSrcDir, androidPackageDir, + "ANDROID"); + if (!result) { + const BuildTargetInfo bti = m_buildSystem->buildTarget(m_buildKey); + QMessageBox::warning( + this, + Tr::tr("Project File not Updated"), + Tr::tr("Could not automatically update the build file for %1.\n" + "Please set %2 manually.") + .arg(bti.projectFilePath.toUserOutput(), Android::Constants::QT_ANDROID_PACKAGE_SOURCE_DIR)); + } } } } diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp index a38f5017216..2ad31eb3bdc 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp @@ -351,14 +351,7 @@ static std::optional<cmListFileFunction> findFunction( return std::make_optional(*function); } -struct SnippetAndLocation -{ - QString snippet; - long line = -1; - long column = -1; -}; - -static SnippetAndLocation generateSnippetAndLocationForSources( +static CMakeBuildSystem::SnippetAndLocation generateSnippetAndLocationForSources( const QString &newSourceFiles, const cmListFile &cmakeListFile, const cmListFileFunction &function, @@ -372,7 +365,7 @@ static SnippetAndLocation generateSnippetAndLocationForSources( "qt6_add_library", "qt_add_qml_module", "qt6_add_qml_module"}; - SnippetAndLocation result; + CMakeBuildSystem::SnippetAndLocation result; int extraChars = 0; auto afterFunctionLastArgument = [&result, &extraChars, newSourceFiles](const auto &f) { @@ -408,8 +401,9 @@ static SnippetAndLocation generateSnippetAndLocationForSources( result.line += extraChars; return result; } + static Result<bool> insertSnippetSilently(const FilePath &cmakeFile, - const SnippetAndLocation &snippetLocation) + const CMakeBuildSystem::SnippetAndLocation &snippetLocation) { BaseTextEditor *editor = qobject_cast<BaseTextEditor *>(Core::EditorManager::openEditorAt( {cmakeFile, int(snippetLocation.line), int(snippetLocation.column)}, @@ -427,6 +421,139 @@ static Result<bool> insertSnippetSilently(const FilePath &cmakeFile, return true; } +CMakeBuildSystem::SnippetAndLocation CMakeBuildSystem::generateSnippetWithTargetPropertyBlock( + const QString &projectName, const QString &snippet, const cmListFile &file) +{ + SnippetAndLocation result; + + result.snippet = QString("\nset_target_properties(%1 PROPERTIES\n %2)\n").arg(projectName, snippet); + + auto findAddExecutableFunction = [&file]() -> std::optional<cmListFileFunction> { + for (const auto &func : file.Functions) { + if (func.LowerCaseName() == "qt_add_executable" || func.LowerCaseName() == "add_executable") { + return func; + } + } + return std::nullopt; + }; + + std::optional<cmListFileFunction> projectFunction = findAddExecutableFunction(); + + if (projectFunction) { + result.line = projectFunction->LineEnd() + 1; + result.column = 0; + } + return result; +} + +static std::vector<cmListFileFunction> findFunctions( + const cmListFile& file, const QString& functionName, const std::string condition) +{ + std::vector<cmListFileFunction> functions; + std::vector<std::string> conditionStack; + + for (const auto& func : file.Functions) { + + if (func.LowerCaseName() == "if") { + for (const auto& arg : func.Arguments()) { + conditionStack.push_back(arg.Value); + } + } else if (func.LowerCaseName() == "elseif") { + if (!conditionStack.empty()) + conditionStack.pop_back(); + for (const auto& arg : func.Arguments()) { + conditionStack.push_back(arg.Value); + } + } else if (func.LowerCaseName() == "else") { + if (!conditionStack.empty()) + conditionStack.pop_back(); + conditionStack.push_back("else"); + } else if (func.LowerCaseName() == "endif") { + if (!conditionStack.empty()) + conditionStack.pop_back(); + } + + if (func.LowerCaseName() == functionName.toLower()) { + bool shouldAdd = false; + + if (conditionStack.empty()) { + shouldAdd = true; + } else { + for (const auto& cond : conditionStack) { + if (cond == "else" || cond.find(condition) != std::string::npos) { + shouldAdd = true; + break; + } + } + } + + if (shouldAdd) + functions.push_back(func); + } + } + + return functions; +} + +static CMakeBuildSystem::SnippetAndLocation generateSnippetForExistingTargetPropertyBlock( + const QString &snippet, const cmListFileFunction &function) +{ + CMakeBuildSystem::SnippetAndLocation result; + int insertLine = function.Line(); + + if (!function.Arguments().empty()) { + const auto &lastArg = function.Arguments().back(); + insertLine = lastArg.Line - 1; + result.column = lastArg.Column + lastArg.Value.length() + 1; + } + + result.line = insertLine + 1; + result.snippet = "\n" + snippet; + + return result; +} + +bool CMakeBuildSystem::setTargetProperty( + ProjectExplorer::Node *context, const QString &property, const QString &value, std::string condition) +{ + if (!context) + return false; + + auto node = dynamic_cast<CMakeTargetNode *>(context); + const QString targetName = node->buildKey(); + + const std::optional<Link> cmakeFile = cmakeFileForBuildKey(targetName, buildTargets()); + if (!cmakeFile) + return false; + + std::optional<cmListFile> cmakeListFile = getUncachedCMakeListFile(cmakeFile->targetFilePath); + if (!cmakeListFile) + return false; + + std::vector<cmListFileFunction> functions = findFunctions(*cmakeListFile, "set_target_properties", condition); + + for (const auto& func : functions) { + for (const auto& args : func.Arguments()) { + if (args.Value == property) { + return false; + } + } + } + + QString snippet; + SnippetAndLocation insertLocation; + + snippet = QString("%1 \"%2\"").arg(property, value); + if (functions.empty()) { + insertLocation = generateSnippetWithTargetPropertyBlock(targetName, snippet, *cmakeListFile); + } else { + insertLocation = generateSnippetForExistingTargetPropertyBlock(snippet, functions[0]); + } + + Result<bool> inserted = insertSnippetSilently(cmakeFile->targetFilePath, insertLocation); + return inserted.value_or(false); +} + static void findLastRelevantArgument(const cmListFileFunction &function, int minimumArgPos, const QSet<QString> &lowerCaseStopParams, diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h index 422964eaecd..67ca14803cb 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h @@ -55,6 +55,21 @@ public: bool addFiles(ProjectExplorer::Node *context, const Utils::FilePaths &filePaths, Utils::FilePaths *) final; + struct SnippetAndLocation + { + QString snippet; + long line = -1; + long column = -1; + }; + + SnippetAndLocation generateSnippetWithTargetPropertyBlock(const QString &projectName, + const QString &snippet, + const cmListFile &file); + + bool setTargetProperty(ProjectExplorer::Node *context, const QString &property, const QString &value, + std::string condition = "") final; + + ProjectExplorer::RemovedFilesFromProject removeFiles(ProjectExplorer::Node *context, const Utils::FilePaths &filePaths, Utils::FilePaths *notRemoved diff --git a/src/plugins/projectexplorer/buildsystem.cpp b/src/plugins/projectexplorer/buildsystem.cpp index 1fb9048576a..288b0351362 100644 --- a/src/plugins/projectexplorer/buildsystem.cpp +++ b/src/plugins/projectexplorer/buildsystem.cpp @@ -188,6 +188,16 @@ bool BuildSystem::addFiles(Node *, const FilePaths &filePaths, FilePaths *notAdd return false; } +bool BuildSystem::setTargetProperty(ProjectExplorer::Node *context, const QString &property, + const QString &value, std::string condition) +{ + Q_UNUSED(context); + Q_UNUSED(property); + Q_UNUSED(value); + Q_UNUSED(condition); + return false; +} + RemovedFilesFromProject BuildSystem::removeFiles(Node *, const FilePaths &filePaths, FilePaths *notRemoved) { diff --git a/src/plugins/projectexplorer/buildsystem.h b/src/plugins/projectexplorer/buildsystem.h index 77fae0a3f16..c22d44412ca 100644 --- a/src/plugins/projectexplorer/buildsystem.h +++ b/src/plugins/projectexplorer/buildsystem.h @@ -178,6 +178,9 @@ public: void updateQmlCodeModel(); virtual void updateQmlCodeModelInfo(QmlCodeModelInfo &projectInfo); + virtual bool setTargetProperty(Node *context, const QString &property, const QString &value, + std::string condition); + signals: void parsingStarted(); void parsingFinished(bool success); |