Created
June 16, 2017 19:02
-
-
Save anonymous/ebdea1483bfeb0d51f94d7fd8167fdb7 to your computer and use it in GitHub Desktop.
Qbs AutoProject
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import qbs | |
import qbs.File | |
import qbs.FileInfo | |
import qbs.TextFile | |
Project | |
{ | |
name: "AutoProject" | |
property string root: sourceDirectory.replace("build/qbs", "") | |
property string src: FileInfo.joinPaths(root, "src") | |
property string include: FileInfo.joinPaths(root, "include") | |
property string target: qbs.targetOS + "-" + (qbs.architecture.contains("x86_64") ? "x64" : qbs.architecture) + "-" + qbs.toolchain.join("-") | |
Probe | |
{ | |
id: scanner | |
property stringList references: [] | |
property path sourceDir: sourceDirectory | |
property string root: sourceDir.replace("build/qbs", "") | |
property string src: FileInfo.joinPaths(root, "src") | |
property string include: FileInfo.joinPaths(root, "include") | |
property string target: qbs.targetOS + "-" + (qbs.architecture.contains("x86_64") ? "x64" : qbs.architecture) + "-" + qbs.toolchain.join("-") | |
configure: | |
{ | |
function printScanResults(subProjects) | |
{ | |
console.info("PROJECT SCANNER RESULTS"); | |
console.info("-----------------------"); | |
console.info(new Date().toLocaleString()); | |
for(i in subProjects) | |
{ | |
console.info(" "); | |
console.info("PROJECT"); | |
console.info(i + " [" + subProjects[i]["dependencies"] + "][" + subProjects[i]["qt"] + "][" + subProjects[i]["includes"] + "]"); | |
console.info(" Public headers: " + subProjects[i]["includables"]); | |
console.info(" Tests:"); | |
for(j in subProjects[i]["tests"]) | |
{ | |
console.info(" " + j + " [" + subProjects[i]["tests"][j]["dependencies"] + "][" + subProjects[i]["tests"][j]["qt"] + "][" + subProjects[i]["tests"][j]["includes"] + "]"); | |
} | |
} | |
console.info("\nEND\n"); | |
} | |
function scanFile(file, includes) | |
{ | |
var f = new TextFile(file); | |
var content = f.readAll(); | |
var regex = /#include <(.*)>/g | |
var include = []; | |
while(include = regex.exec(content)) | |
{ | |
var inc = include[1]; | |
if(!includes.contains(inc)) | |
{ | |
includes.push(inc); | |
} | |
} | |
} | |
function scanTests(path, tests) | |
{ | |
var testFiles = File.directoryEntries(path, File.Files); | |
for(i in testFiles) | |
{ | |
var testFile = testFiles[i]; | |
if(testFile.endsWith(".cpp")) | |
{ | |
var test = FileInfo.completeBaseName(testFile); | |
var includes = []; | |
scanFile(FileInfo.joinPaths(path, testFile), includes); | |
var headerFile = FileInfo.joinPaths(path, test + ".h"); | |
if(File.exists(headerFile)) | |
{ | |
scanFile(headerFile, includes); | |
} | |
var testObj = {}; | |
testObj["includes"] = includes; | |
testObj["dependencies"] = [ "cpp" ]; | |
testObj["qt"] = ["core", "testlib"]; | |
testObj["includePaths"] = []; | |
tests[test] = testObj; | |
} | |
} | |
} | |
function scanProject(root, name) | |
{ | |
var project = {}; | |
var includes = []; | |
//includable files | |
var includables = File.directoryEntries(FileInfo.joinPaths(root, "include", name), File.Files); | |
for(i in includables) | |
{ | |
scanFile(FileInfo.joinPaths(root, "include", name, includables[i]), includes); | |
} | |
//source files | |
var srcFiles = File.directoryEntries(FileInfo.joinPaths(root, "src", name), File.Files); | |
for(i in srcFiles) | |
{ | |
scanFile(FileInfo.joinPaths(root, "src", name, srcFiles[i]), includes); | |
} | |
//private source files | |
var privateFiles = File.directoryEntries(FileInfo.joinPaths(root, "src", name, "private"), File.Files); | |
for(i in privateFiles) | |
{ | |
scanFile(FileInfo.joinPaths(root, "src", name, "private", privateFiles[i]), includes); | |
} | |
//tests | |
var tests = {}; | |
scanTests(FileInfo.joinPaths(root, "src", name, "tests"), tests); | |
project["includables"] = includables; | |
project["includes"] = includes; | |
project["tests"] = tests; | |
project["dependencies"] = [ "cpp" ]; | |
project["qt"] = [ "core" ]; | |
project["includePaths"] = [ "project.root + \"/private\"", " project.include" ]; | |
return project; | |
} | |
function getQtModule(include) | |
{ | |
var module = "core"; | |
// var qtmodules = {}; | |
// qtmodules["core"] = [""]; | |
// qtmodules["gui"] = [""]; | |
// qtmodules["network"] = [""]; | |
// qtmodules["qml"] = [""]; | |
// qtmodules["sql"] = [""]; | |
// qtmodules["testlib"] = [""]; | |
// qtmodules["widgets"] = [""]; | |
// qtmodules["websockets"] = [""]; | |
// for(i in qtmodules) | |
// { | |
// if(qtmodules[i].contains(include)) | |
// { | |
// module = i; | |
// break; | |
// } | |
// } | |
return module; | |
} | |
function buildProjectDep(name, project, subProjects) | |
{ | |
for(include in project["includes"]) | |
{ | |
var val = project["includes"][include]; | |
if(val.startsWith("Q")) | |
{ | |
var qtModule = getQtModule(val); | |
if(!project["qt"].contains(qtModule)) | |
{ | |
project["qt"].push(qtModule); | |
} | |
} | |
else | |
{ | |
for(other in subProjects) | |
{ | |
if(other == name || project["dependencies"].contains(other)) | |
{ | |
continue; | |
} | |
else if(subProjects[other]["includables"].contains(val)) | |
{ | |
project["includePaths"].push("project.includeRoot + \"/" + other + "\""); | |
project["dependencies"].push(other); | |
} | |
} | |
} | |
} | |
} | |
function buildDependencies(subProjects) | |
{ | |
for(project in subProjects) | |
{ | |
for(test in subProjects[project]["tests"]) | |
{ | |
buildProjectDep(test, subProjects[project]["tests"][test], subProjects); | |
} | |
buildProjectDep(project, subProjects[project], subProjects); | |
} | |
} | |
function prepareTemp(temp) | |
{ | |
if(File.exists(temp)) | |
{ | |
File.remove(temp); | |
} | |
File.makePath(temp); | |
} | |
function writeProjects(subProjects, temp) | |
{ | |
for(project in subProjects) | |
{ | |
var fileName = project + ".qbs"; | |
var filePath = FileInfo.joinPaths(temp, fileName); | |
var f = new TextFile(filePath, TextFile.WriteOnly); | |
var content = | |
"import qbs\n" | |
+ "\n" | |
+ "Project\n" | |
+ "{\n" | |
+ " name: \"" + project + "\"\n" | |
+ " property string root: project.src + \"/\" + name\n" | |
+ " property path include: project.include + \"/\" + name\n" | |
+ " property path includeRoot: project.include\n" | |
+ " property path target: project.target\n" | |
+ "\n" | |
+ " DynamicLibrary\n" | |
+ " {\n"; | |
//Dependencies | |
for(dep in subProjects[project]["dependencies"]) | |
{ | |
content += " Depends { name: \"" + subProjects[project]["dependencies"][dep] + "\" }\n"; | |
} | |
var qtModules = []; | |
for(dep in subProjects[project]["qt"]) | |
{ | |
qtModules.push("\"" + subProjects[project]["qt"][dep] + "\""); | |
} | |
content += | |
" Depends { name: \"Qt\"; submodules: [ " + qtModules.join() + " ]; }\n" | |
+ "\n" | |
+ " name: project.name\n" | |
+ " targetName: qbs.buildVariant == \"debug\" ? name + \"d\" : name\n" | |
+ " cpp.includePaths: [ " + subProjects[project]["includePaths"].join() + " ]\n" | |
+ " cpp.defines: product.name.toUpperCase() + \"_LIB\"\n" | |
+ " files: [ project.include + \"/*.h\", project.root + \"/*.cpp\", project.root + \"/private/*.h\", project.root + \"/private/*.cpp\" ]\n" | |
+ "\n" | |
+ " Group\n" | |
+ " {\n" | |
+ " qbs.install: true\n" | |
+ " qbs.installDir: project.target\n" | |
+ " fileTagsFilter: [ \"dynamiclibrary\" ]\n" | |
+ " }\n" | |
+ " }\n" | |
+ "\n" | |
+ " //Documentation\n" | |
+ " Product\n" | |
+ " {\n" | |
+ " name: project.name + \"Doc\"\n" | |
+ " files: project.root + \"/doc/*qdoc\"\n" | |
+ " }\n" | |
+ "\n" | |
+ " Project\n" | |
+ " {\n" | |
+ " name: project.name + \"Tests\"\n" | |
+ " property string root: project.root\n" | |
+ " property string includeRoot: project.includeRoot\n" | |
+ "\n"; | |
//tests | |
for(test in subProjects[project]["tests"]) | |
{ | |
content += " QtApplication\n {\n"; | |
for(dep in subProjects[project]["tests"][test]["dependencies"]) | |
{ | |
content += " Depends { name: \"" + subProjects[project]["tests"][test]["dependencies"][dep] + "\" }\n"; | |
} | |
qtModules = []; | |
for(dep in subProjects[project]["tests"][test]["qt"]) | |
{ | |
qtModules.push("\"" + subProjects[project]["tests"][test]["qt"][dep] + "\""); | |
} | |
content += | |
" Depends { name: \"Qt\"; submodules: [" + qtModules.join() + "]; }\n" | |
+ "\n" | |
+ " name: \"" + test + "\"\n" | |
+ " targetName: qbs.buildVariant == \"debug\" ? name + \"d\" : name\n" | |
+ " cpp.includePaths: [ " + subProjects[project]["tests"][test]["includePaths"].join() + " ]\n" | |
+ " files: [ project.root + \"/tests/" + test + "*\" ]\n" | |
+ "\n" | |
+ " Group\n" | |
+ " {\n" | |
+ " qbs.install: true\n" | |
+ " qbs.installDir: project.target\n" | |
+ " fileTagsFilter: [ \"application\" ]\n" | |
+ " }\n" | |
+ " }\n" | |
+ "\n"; | |
} | |
content += " }\n}\n"; | |
f.write(content); | |
f.close(); | |
references.push(filePath); | |
} | |
} | |
if(File.exists(src)) | |
{ | |
var subProjects = {}; | |
var subProjectNames = File.directoryEntries(src, File.Dirs | File.NoDotAndDotDot); | |
for(i in subProjectNames) | |
{ | |
subProjects[subProjectNames[i]] = scanProject(root, subProjectNames[i]); | |
} | |
buildDependencies(subProjects); | |
printScanResults(subProjects); | |
var temp = FileInfo.joinPaths(sourceDir, "temp"); | |
prepareTemp(temp); | |
writeProjects(subProjects, temp); | |
} | |
else | |
{ | |
console.error("Directory '" + src + "' does not exist"); | |
} | |
} | |
} | |
references: scanner.references | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment