[QBS] Depends and cpp.includePaths

Ruslan Nigmatullin EuroElessar at yandex.ru
Mon Feb 27 16:00:54 CET 2012



27.02.2012, 20:32, "Joerg Bornemann" <joerg.bornemann at nokia.com>:
> On 27/02/2012 13:22, ext Ruslan Nigmatullin wrote:
>
>>  Is qbs user have to name directory with sources in the same way and the same structure as it will be installed in /usr/include directory? Or user must have external pregenerated directory with pseudo headers fore each included header for each "possibly-not-system" library in source dir (for example libpng)?
>
> No the user doesn't have to use the same directory layout for its source
> tree and the installed headers. See tests/manual/localDeployment for an
> example.
>
>>  Currently qbs doesn't handle dependencies to generated headers at all
>
> (so boo.cpp, which includes foo.h, can be processed before foo.h will be
> generated, which leads to compile error).
>
> Of course does qbs handle dependencies to generated headers. Otherwise
> building Qt programs with .ui files wouldn't work at all.
> Can you provide an example of something that's broken?

Of course, run "qbs -j1" on this project, the issue is that generated header doesn't belong to current product:

------ 1.txt ------
Hello from first header

------ 2.txt ------
Hello from second header

------ headergen.qbp ------
import qbs.base 1.0
import qbs.fileinfo 1.0 as FileInfo

Project {
    property string name: 'headergen'
    
    Product {
        type: 'application'
        name: "secondapp"
        files: [
            "main.cpp"
        ]
        Group {
            files: [ '1.txt' ]
            fileTags: ['text']
        }
        Depends { name: 'cpp' }
        Depends { name: project.name }
        cpp.includePaths: [
            buildDirectory
        ]
    }
    
    Product {
        type: 'application'
        name: project.name
        files: [
            "main.cpp"
        ]
        Group {
            files: [ '2.txt' ]
            fileTags: ['text']
        }
        Depends { name: 'cpp' }
        cpp.includePaths: [
            buildDirectory
        ]
    }

    Rule {
        inputs: ['text']
        Artifact {
            fileTags: ['hpp']
            fileName: "long/long/" + input.baseName + '.h'
        }
        prepare: {
            var cmd = new JavaScriptCommand();
            cmd.varName = "GREETINGS_FROM_" + output.fileName.replace(/.*long\//, "").replace(/.h/, "");
            cmd.sourceCode = function () {
                File.remove(output.fileName);
                var file = new TextFile(input.fileName, TextFile.ReadOnly);
                var text = file.readAll();
                file = new TextFile(output.fileName, TextFile.WriteOnly);
                file.truncate();
                file.write("#define " + varName + " \"" + text.replace(/\n/, "\" \\\n\"") + "\"");
                file.close();
            }
            cmd.description = 'generating ' + FileInfo.fileName(output.fileName);
            cmd.highlight = 'codegen';
            return cmd;
        }
    }

}


------ main.cpp ------
#include <cstdio>
#include <cstdlib>
#include <long/long/1.h>
#include <long/long/2.h>

int main()
{
    printf("%s\n%s\n", GREETINGS_FROM_1, GREETINGS_FROM_2);
    return EXIT_SUCCESS;
}


>>  The same issue is reproduced if "cpp" file is generated and it contains Q_OBJECT macro (Generated file "boo.cpp" contains directive for including "boo.moc"). Automoc doesn't handle it at all (as file is not created at the moment when check is performing). If tag "moc_cpp" is set manually qbs crashes. If crash is fixed and artifact for moc is created cpp's "obj" parent doesn't depend on it, so "g++" is called before "moc" and it again leads to compile error.
>
> That automoc thingy cannot handle generated files ATM. That's true.
>
>>  The only way I found is to scan file for dependencies again right after it was generated and reapplying rules for it (that will add "moc_*" tag for generated files with Q_OBJECT macro). Also may be it's needed to check somehow for generatable headers at includes processing state. For example if "generated/foo.h" with fileTag "hpp" is generated by Rule from "foo.txt" and "boo.cpp" contains "#include<generated/foo.h>" the last one should depend on "foo.h".
>
> Why does your .cpp generator not know whether its generating .cpp files
> that need to be moc'ed? It could just add the "moc_cpp" and "cpp"
> filetags and doesn't have to rely on automoc.

qbs segfaults on this project, I've tried to fix segfault, but with my fix dependencies are not generated correctly and bla.moc is generating after compiling of bla.cpp:

------ bla.txt ------
#include <QObject>

class MyObject : public QObject
{
    Q_OBJECT
};

int main()
{
    MyObject obj;
    return 0;
}

#include "bla.moc"


------ moc_cpp.qbp ------
import qbs.base 1.0
import qbs.fileinfo 1.0 as FileInfo

Project {
    Product {
        type: "application"
        name: "moc_cpp"

        Depends {
            name: "Qt.core"
        }

        Group {
            files: 'bla.txt'
            fileTags: ['text']
        }
    }

    Rule {
        inputs: ['text']
        Artifact {
            fileTags: ['cpp', 'moc_cpp']
            fileName: input.baseName + '.cpp'
        }
        prepare: {
                        var cmd = new JavaScriptCommand();
                        cmd.sourceCode = function () {
                                var file = new TextFile(input.fileName, TextFile.ReadOnly);
                                var text = file.readAll();
                                file = new TextFile(output.fileName, TextFile.WriteOnly);
                                file.truncate();
                                file.write(text);
                                file.close();
                        }
                        cmd.description = 'generating ' + FileInfo.fileName(output.fileName);
                        cmd.highlight = 'codegen';
                        return cmd;
        }
    }
}



More information about the Qbs mailing list