[QBS] propagate compiler options

Marcel Mulder marcel.mulder at xs4all.nl
Wed Jan 21 19:46:21 CET 2015


Hi,

I want to let you know what my final setup is. The RTOS.qbs example made be think about the compiler flags. So my project file now looks like this:

import qbs 1.0

Project {
    references: [
        "wsbd-app.qbs",
        "ccflags.qbs",
        "includes.qbs",
        "board.qbs",
        "hal.qbs",
        "kernel.qbs",
    ]
}

In the ccflags.qbs I have all my compiler settings. Something like:

import qbs 1.0

Product {
    name: "ccflags"
    Export {
        Depends { name: 'cpp' }
        cpp.commonCompilerFlags: [
            "-mcpu=cortex-m4","-mthumb","-mabi=aapcs","-mfloat-abi=hard","-mfpu=fpv4-sp-d16",
            "-std=gnu99",
            "-fomit-frame-pointer","-falign-functions=16","-fdata-sections","-ffunction-sections","-fno-common",
            "-Wstrict-prototypes"
        ]
        cpp.linkerFlags:[
            "-mthumb", "-mabi=aapcs",
            "-Los/ports/GCC/ARMCMx",
            "-TSTM32F429xI.ld",
            "-mcpu=cortex-m4","-mthumb","-mabi=aapcs","-mfloat-abi=hard","-mfpu=fpv4-sp-d16",
            "-Wl,--gc-sections","--specs=nano.specs","-nostartfiles",
        ]
        cpp.defines: [
            "THUMB",
        ]
        cpp.warningLevel: "all" //"all" // or "none", "default"
        cpp.treatWarningsAsErrors: true
        cpp.positionIndependentCode: false

        Properties {
            condition: qbs.buildVariant === "debug"
            cpp.debugInformation: true
            cpp.optimization: "none"
        }
        Properties {
            condition: qbs.buildVariant === "release"
            cpp.debugInformation: false
            cpp.optimization: "small"
        }
    }
}

The include.qbs is similar for all include paths. Now also the other product depend on this, like:

import qbs 1.0

Product {
    type: "application"
    name: “example"

    Depends { name: "cpp" }
    Depends { name: "kernel" }
    Depends { name: "hal" }
    Depends { name: "board" }
    Depends { name: "ccflags" }
    Depends { name: "includes" }

    cpp.embedInfoPlist : false // Mac OS X work arround
    cpp.executableSuffix: ".out"
    files: [
        "main.c", "usbcfg.c",
    ]
}

This works great and has no cross dependencies. The only thing thats bothering me, is that the compiler flags are now a product.
Thats not something I thought of when I started this project. And I think I am not the only one.
There is one tiny thing I do not understand. In my main product about I have the line:
    cpp.executableSuffix: ".out"
If I have that line in de ccflags.qbs than the output file will be .a instead of .out. So he is ignoring the line in de ccflags.qbs but all other flags are used.
Something I do not comprehend. 

Anyway. I am happy with my setup.

Best regards, Marcel

> On 19 Jan 2015, at 18:17, Marcel Mulder <marcel.mulder at xs4all.nl> wrote:
> 
> Hi all,
> 
> I have a working setup now using the idea with the RTOS.qbs and using project properties to propagate the compiler options. But I don’t really like it.
> Suggestions of using batch or script files are good for a temporarily solutions but it is not really an option if you want to become a serious build system. All administration to build a system should be in the qbs files. The only thing you want to define on the command line is what should be build and what to use for the build and a few build options or variants. I also use QT creator a lot and don’t want to customise stuff there. 
> 
> I hope the qbs developers find a way of propagating compiler settings and defines and also think of way to deal with cross dependencies. Maybe via inheritance or via access to the top level product via the project property. Because I think that using javascript and start coding in a build system for simple things every build system can do is very strange and unwanted. Qbs is clean and I like it. Lets keep it that way ;-)
> I want to participate and give my input because I have ideas how to implement it neatly. But I got the feeling it is not very welcome.
> 
> I want to thank Thomas, Andrii and Richard for there input. That was very valuable!
> 
> Best regards, Marcel
> 
> 
>> On 18 Jan 2015, at 11:02, Thomas Epting <thomas.epting.stryker at gmail.com <mailto:thomas.epting.stryker at gmail.com>> wrote:
>> 
>> > property stringList myIncludePaths: [ path ]
>> > But I read in the mail list that using path is deprecated.
>> > What is the future way to go? Using sourceDirectory?
>> 
>> Even though "path" is deprecated now, its functionalitiy will available in the future. You just have to migrate to whatever the coming Qbs versions will provide as a replacement.
>> 
>> > I have for example application A which depend on static
>> > library B and C. Static library B depends on static library C.
>> > No problem yet but now static library C depends on B.
>> > [...] Mostly they are configuration dependenties.
>> 
>> So I would try merging all these configuration dependencies in one place, and let A, B and C depend on them. A very simple approach would be to introduce a common product, which exports the configuration stuff.
>> 
>> --- RTOS.qbs ---
>> import qbs 1.0
>> Product {
>>     Export {
>>         Depends { name: "cpp" }
>>         cpp.includePaths: ...
>>         cpp.defines: ...
>>     }
>> }
>> 
>> Now let A, B and C depend on RTOS. You can even consider adding project level properties in the exported stuff (haven't tried this, but I think it should work). Or, consider Richards approach, which also sounds very good.
>> 
>> > The property as you proposed is a nice solution with the
>> > current implementation of qbs. The drawback is that
>> > independent projects like a RTOS, or libraries supporting
>> > qbs have to also support my naming convention of the properties.
>> 
>> Of course it has to be done the other way round. The generic product has to provide a solution, and you have to adopt to it. So your RTOS could define a set of properties which it expects to be available at project level (e.g. rtosIncludePaths, rtosDefines, rtosCxxFlags, ...). They can even check if these properties exist and react accordingly, e.g. by using JavaScript like if (project.rtosDefines === undefined).
>>  
>> > What if you have application A which is depending on static
>> > library B. Now you have a define in your code and in the
>> > library code to disalbe a certain feature like: [...]
>> 
>> You could either depend both A and B on a common product like Features.qbs, which exports the defines you need. Or, define the features on project level and let A and B query them. Here's a sketch for the latter:
>> 
>> --- Project.qbs ---
>> import qbs 1.0
>> Project {
>>     property bool hasFeatureA: true
>>     property bool hasFeatureB: false
>> }
>> 
>> --- A.qbs ---
>> import qbs 1.0
>> Application {
>>     Depends { name: "cpp" }
>>     cpp.defines: {
>>         var defs = [ ]
>>         if (!project.hasFeatureA)
>>             defs.push("DISABLE_FEATURE_A")
>>         ...
>>         return defs
>>     }
>> }
>> 
>> --- B.qbs ---
>> import qbs 1.0
>> StaticLibary {
>>     Depends { name: "cpp" }
>>     cpp.defines: {
>>         var defs = [ ]
>>         if (!project.hasFeatureA)
>>             defs.push("DISABLE_FEATURE_A")
>>         ...
>>         return defs
>>     }
>> }
>> 
>> Regards,
>> Thomas
> 
> _______________________________________________
> QBS mailing list
> QBS at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/qbs

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/qbs/attachments/20150121/550e4246/attachment.html>


More information about the Qbs mailing list