Skip to content

Instantly share code, notes, and snippets.

Created June 16, 2017 19:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/ebdea1483bfeb0d51f94d7fd8167fdb7 to your computer and use it in GitHub Desktop.
Save anonymous/ebdea1483bfeb0d51f94d7fd8167fdb7 to your computer and use it in GitHub Desktop.
Qbs AutoProject
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