From 71f58af02e48048beb9f08d2481aabc2cb3df1b8 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Mon, 13 Feb 2023 19:59:07 +0200 Subject: [PATCH] Support for conan package manager. --- conanfile.txt | 2 + qbs/module-providers/conan/provider.qbs | 124 ++++++++++++++++++ qbs/modules/buildconfig/buildconfig.qbs | 11 ++ src/app/tape/tape.qbs | 1 + src/libs/ifc/ifc.qbs | 14 +- src/test/CollectionTest/CollectionTest.qbs | 1 + .../TranslationsTest/TranslationsTest.qbs | 1 + valentina.qbs | 17 +++ 8 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 conanfile.txt create mode 100644 qbs/module-providers/conan/provider.qbs diff --git a/conanfile.txt b/conanfile.txt new file mode 100644 index 000000000..df6ca348b --- /dev/null +++ b/conanfile.txt @@ -0,0 +1,2 @@ +[requires] +xerces-c/[>=3.2,<4.0] diff --git a/qbs/module-providers/conan/provider.qbs b/qbs/module-providers/conan/provider.qbs new file mode 100644 index 000000000..19ff4561a --- /dev/null +++ b/qbs/module-providers/conan/provider.qbs @@ -0,0 +1,124 @@ +import qbs.File +import qbs.FileInfo +import qbs.TextFile + +ModuleProvider { + relativeSearchPaths: { + var conanPackageDir = FileInfo.cleanPath(FileInfo.joinPaths(outputBaseDir, "../../..", "genconan")); + var dirs = File.directoryEntries(conanPackageDir, File.AllDirs | File.NoDotAndDotDot); + var packageVersions = {}; + + /* + * The generated conanbuildinfo.json files are inside of the 'genconan' folder in the build directory. + * Since there might be more than one, they're placed inside of folders with a hashed name to avoid conflicts. + * Here we have to iterate over those folders and process the json files within. + */ + for(d in dirs) { + var conanbuildinfo = FileInfo.joinPaths(conanPackageDir, dirs[d], "conanbuildinfo.json"); + + if(!File.exists(conanbuildinfo)) { + continue; + } + + var file = new TextFile(conanbuildinfo, TextFile.ReadOnly); + var fileContent = JSON.parse(file.readAll()); + + file.close(); + + console.info(JSON.stringify(fileContent)); + + var deps = fileContent.dependencies; + + for(i in deps){ + if(packageVersions[deps[i].name]) { + if(deps[i].version != packageVersions[deps[i].name]) { + console.error("Conan package '" + deps[i].name + "' found in multiple conanfile.txt's with different versions: " + + packageVersions[deps[i].name] + " and " + deps[i].version); + + return []; + } + + console.info("Already generated module for conan package '" + deps[i].name + "', skipping...") + + continue; + } + + console.info("Generating module for conan package '" + deps[i].name + "'"); + packageVersions[deps[i].name] = deps[i].version; + + // module name can be invalid for Javascrip. Search for alternative names for cmake. + var moduleName = deps[i].name; + if (deps[i].hasOwnProperty("names")) + { + if (deps[i].names.hasOwnProperty("cmake_find_package")) + moduleName = deps[i].names.cmake_find_package; + else if (deps.names.hasOwnProperty("cmake_find_package_multi")) + moduleName = deps[i].names.cmake_find_package_multi; + } + + var moduleDir = FileInfo.joinPaths(outputBaseDir, "modules", name, moduleName); + + File.makePath(moduleDir); + + var moduleFile = new TextFile(FileInfo.joinPaths(moduleDir, moduleName + ".qbs"), TextFile.WriteOnly); + + var shared = false; + if (fileContent.options[deps[i].name].hasOwnProperty("shared")) + { + shared = (fileContent.options[deps[i].name].shared === 'True'); + } + + var cppLibraries = shared ? "\tcpp.dynamicLibraries: " : "\tcpp.staticLibraries: "; + + moduleFile.write("import qbs\n" + + "Module {\n" + + "\tproperty bool installBin: false\n" + + "\tproperty bool installLib: false\n" + + "\tproperty bool installRes: false\n" + + "\tproperty bool installInclude: false\n" + + "\tproperty string binInstallDir: \"bin\"\n" + + "\tproperty string libInstallDir: \"lib\"\n" + + "\tproperty string resInstallDir: \"res\"\n" + + "\tproperty string includeInstallDir: \"include\"\n" + + "\tproperty stringList binFilePatterns: [\"**/*\"]\n" + + "\tproperty stringList libFilePatterns: [\"**/*\"]\n" + + "\tproperty stringList resFilePatterns: [\"**/*\"]\n" + + "\tproperty stringList includeFilePatterns: [\"**/*\"]\n\n" + + "\tDepends { name: \"cpp\" }\n\n" + + "\tcpp.includePaths: " + JSON.stringify(deps[i].include_paths) + "\n" + + "\tcpp.systemIncludePaths: " + JSON.stringify(deps[i].include_paths) + "\n" + + "\tcpp.libraryPaths: " + JSON.stringify(deps[i].lib_paths) + "\n" + + cppLibraries + JSON.stringify(deps[i].libs) + "\n" + + "\tcpp.defines: " + JSON.stringify(deps[i].defines) + "\n\n"); + + function writeGroups(file, moduleName, prefix, pathList, install) { + for(j in pathList) { + file.write("\tGroup {\n" + + "\t\tname: \"" + prefix + (j > 0 ? j : "") + "\"\n" + + "\t\tprefix: \"" + FileInfo.fromNativeSeparators(pathList[j]) + "/\"\n" + + "\t\tfilesAreTargets: true\n"); + + if (install) + file.write("\t\tqbs.install: product.conan." + moduleName + ".install" + (prefix.charAt(0).toUpperCase() + prefix.substring(1)) + "\n" + + "\t\tqbs.installPrefix: \"\"\n" + + "\t\tqbs.installDir: product.conan." + moduleName + "." + prefix + "InstallDir\n" + + "\t\tqbs.installSourceBase: \"" + FileInfo.fromNativeSeparators(pathList[j]) + "\"\n"); + + file.write("\t\tfiles: product.conan." + moduleName + "." + prefix + "FilePatterns\n" + + "\t}\n"); + } + } + + writeGroups(moduleFile, moduleName, "bin", deps[i].bin_paths, true); + writeGroups(moduleFile, moduleName, "lib", deps[i].lib_paths, shared); + writeGroups(moduleFile, moduleName, "res", deps[i].res_paths, true); + writeGroups(moduleFile, moduleName, "include", deps[i].include_paths, shared); + + moduleFile.writeLine("}"); + moduleFile.close(); + } + } + + return [""]; + } +} diff --git a/qbs/modules/buildconfig/buildconfig.qbs b/qbs/modules/buildconfig/buildconfig.qbs index e2657143b..a3ff07fe9 100644 --- a/qbs/modules/buildconfig/buildconfig.qbs +++ b/qbs/modules/buildconfig/buildconfig.qbs @@ -37,6 +37,17 @@ Module { property bool treatWarningsAsErrors: true + readonly property bool useConanPackages : { + if (Utilities.versionCompare(Qt.core.version, "6") < 0) + return false; + + if (qbs.targetOS.contains("unix") && !qbs.targetOS.contains("macos")) + { + return project.enableConan; + } + return true; + } + property string libDirName: "lib" property string appTarget diff --git a/src/app/tape/tape.qbs b/src/app/tape/tape.qbs index 356714744..b53ec97c1 100644 --- a/src/app/tape/tape.qbs +++ b/src/app/tape/tape.qbs @@ -14,6 +14,7 @@ VToolApp { Depends { name: "VToolsLib"; } Depends { name: "ebr" } Depends { name: "multibundle"; } + Depends { name: "conan.XercesC"; condition: buildconfig.useConanPackages } name: "Tape" buildconfig.appTarget: qbs.targetOS.contains("macos") ? "Tape" : "tape" diff --git a/src/libs/ifc/ifc.qbs b/src/libs/ifc/ifc.qbs index d27ccfc16..096d3109c 100644 --- a/src/libs/ifc/ifc.qbs +++ b/src/libs/ifc/ifc.qbs @@ -11,8 +11,17 @@ VLib { Depends { name: "xerces-c" - condition: Utilities.versionCompare(Qt.core.version, "6") >= 0 && qbs.targetOS.contains("unix") - && !qbs.targetOS.contains("macos") + condition: !buildconfig.useConanPackages + } + + Depends { + name: "conan.XercesC" + condition: buildconfig.useConanPackages + } + + Properties { + condition: buildconfig.useConan && (qbs.targetOS.contains("macos") || qbs.targetOS.contains("windows")) + conan.XercesC.installLib: true } name: "IFCLib" @@ -96,6 +105,7 @@ VLib { Depends { name: "cpp" } Depends { name: "Qt"; submodules: ["xml"] } Depends { name: "VMiscLib" } + Depends { name: "conan.XercesC"; condition: buildconfig.useConanPackages } cpp.includePaths: [exportingProduct.sourceDirectory] } } diff --git a/src/test/CollectionTest/CollectionTest.qbs b/src/test/CollectionTest/CollectionTest.qbs index 228abf5f9..d939a4a8f 100644 --- a/src/test/CollectionTest/CollectionTest.qbs +++ b/src/test/CollectionTest/CollectionTest.qbs @@ -5,6 +5,7 @@ VTestApp { Depends { name: "buildconfig" } Depends { name: "Qt"; submodules: ["testlib", "gui", "printsupport"] } Depends { name: "VTestLib" } + Depends { name: "conan.XercesC"; condition: buildconfig.useConanPackages } name: "CollectionTest" buildconfig.appTarget: qbs.targetOS.contains("macos") ? "CollectionTest" : "collectionTest" diff --git a/src/test/TranslationsTest/TranslationsTest.qbs b/src/test/TranslationsTest/TranslationsTest.qbs index ea1804a95..daceab860 100644 --- a/src/test/TranslationsTest/TranslationsTest.qbs +++ b/src/test/TranslationsTest/TranslationsTest.qbs @@ -4,6 +4,7 @@ VTestApp { Depends { name: "buildconfig" } Depends { name: "VTestLib" } Depends { name: "Qt"; submodules: ["testlib", "xml", "gui", "printsupport"] } + Depends { name: "conan.XercesC"; condition: buildconfig.useConanPackages } name: "TranslationsTest" buildconfig.appTarget: qbs.targetOS.contains("macos") ? "TranslationsTest" : "translationsTest" diff --git a/valentina.qbs b/valentina.qbs index 38c2f2971..956488c5e 100644 --- a/valentina.qbs +++ b/valentina.qbs @@ -1,6 +1,23 @@ +import qbs.Probes + Project { name: "Valentina" minimumQbsVersion: "1.16" + + property bool enableConan: false + + Probes.ConanfileProbe { + id: thirdPartyConanPackages + condition: enableConan + conanfilePath: project.sourceDirectory + "/conanfile.txt" + options: { + if (qbs.targetOS.contains("unix") && !qbs.targetOS.contains("macos")) + return ({"xerces-c:shared": "False"}); + + return ({"xerces-c:shared": "True"}); + } + } + references: [ "src/src.qbs", "share/translations/translations.qbs",