[Qbs] Order of property evaluation

Christian Kandeler christian.kandeler at qt.io
Tue May 8 17:10:54 CEST 2018


On Tue, 8 May 2018 16:17:10 +0200
<resurrection at centrum.cz> wrote:

> I am a bit confused about the order in which the various variables are initialized in Qbs. For example the documentation for variable `product.name` says that it cannot depend on any other property

On any *module* property.

> and yet the invalid example:
>  
> CppApplication {
>     name: "app_" + qbs.targetOS.join("_")
>     // invalid
> }
>  
> actually works just fine. 

It's not *guaranteed* to work. That does not exclude it from actually working under some circumstances or even most of the time. The documentation tells you: The "name" property is special and you should not make it depend on module properties. If you choose to ignore that, you cannot complain if your project breaks in the future.

> When trying to use multiplexing however there are no explicit restrictions in the docs but I found out that those variables actually cannot depend on others. When set to for example probe result:
>  
> CppApplication {
>     Probe {
>         id: myprobe
>         property stringList architectures: []
>         configure: {
>             architectures = ["x86", "x86_64"]
>             found: true
>         }
>     }
>     
>     qbs.architectures: myprobe.architectures
> }
>  
> It does not work and the multiplexing is not triggered. No error or warning is given.

Multiplexing happens *very* early in the project resolving process. Here's what happens in your example:
    - (0) The product item is read, and the qbs module is loaded.
    - (1) qbs.architectures is evaluated. Because the probe has not yet run, myprobe.architectures is the initial value, i.e. the empty array.
    - (2) The multiplexing algorithm does nothing, because the respective array properties do not contain any values.
    - (3) More modules are being loaded etc.
    - (4) Module-level probes are run.
    - (5) Product-level probes are run.
After step (5), qbs.architectures does have the value ["x86", "x86_64"], but the multiplexing phase is long over.
So it is indeed expected that your code does not do what you want it to. I think a variation of this could be made to work, if the Probe goes to the surrounding Project item. (It does not work at the moment, because project-level Probes are also run after product multiplexing, but I don't think there is a technical reason for that.)

> And that last part somewhat bother me because there is uncertainty as to the order of evaluation of properties and which properties can rely on others. I have already found out that for some properties in a product the order does not matter so this:
>  
> CppApplication {
>     targetName: name + "_"
>     name: "MyApp"
> }
>  
> Will produce "MyApp_" as targetName

Property order should never matter. 

> however this:
>  
> Product {
>     cpp.cxxFlags: "-myflag"
>     Depends { name: "cpp" }
> }
>  
> Will produce error saying that cpp variable was not declared.

I cannot reproduce that.

> It kind of reminds me of what bothered me about qmake. I would personally prefer strict top-down evaluation order. While it could add ability to "re-use" properties or change them during evaluation in different parts of the product it would in my opinion solve a lot of confusion about what is evaluated when and what can be used in what contexts, e.g. probe/properties in multiplexing properties etc.

Declaration order matters in some places, e.g. if a Depends condition references a property of another module, or a Probe's input makes use of another Probe's output. But this is only between things in the same "phase". You cannot just process things in textual order, with no regards to semantics.


Christian



More information about the Qbs mailing list