简体   繁体   English

QBS:在产品内部明确设置qbs.profiles导致构建失败

[英]QBS: Explicitly setting qbs.profiles inside Products causing build to fail

My use-case is this: 我的用例是这样的:

I have a static library which I want to be available for some profiles (eg "gcc", "arm-gcc", "mips-gcc"). 我有一个静态库,希望对某些配置文件可用(例如“ gcc”,“ arm-gcc”,“ mips-gcc”)。

I also have an application which links to this library, but this applications should only build using a specific profile (eg "arm-gcc"). 我也有一个链接到该库的应用程序,但是该应用程序只能使用特定的配置文件(例如“ arm-gcc”)进行构建。

For this I am modifying the app-and-lib QBS example. 为此,我正在修改app-and-lib QBS示例。

The lib.qbs file: lib.qbs文件:

import qbs 1.0

Product {
    qbs.profiles: ["gcc", "arm-gcc", "mips-gcc"] //I added only this line
    type: "staticlibrary"
    name: "mylib"
    files: [
        "lib.cpp",
        "lib.h",
    ]
    Depends { name: 'cpp' }
    cpp.defines: ['CRUCIAL_DEFINE']

    Export {
        Depends { name: "cpp" }
        cpp.includePaths: [product.sourceDirectory]
    }
}

The app.qbs file: app.qbs文件:

import qbs 1.0

Product {
    qbs.profiles: ["arm-gcc"] //I added only this line
    type: "application"
    consoleApplication: true
    files : [ "main.cpp" ]
    Depends { name: "cpp" }
    Depends { name: "mylib" }
}

The app build fails. 应用程序构建失败。 Qbs wrongly tries to link to the "gcc" version of the library instead of the "arm-gcc" version, as you can see in the log: Qbs错误地尝试链接到库的“ gcc”版本而不是“ arm-gcc”版本,如您在日志中所看到的:

Build graph does not yet exist for configuration 'default'. Starting from scratch.
Resolving project for configuration default
Setting up build graph for configuration default
Building for configuration default
compiling lib.cpp [mylib {"profile":"gcc"}]
compiling lib.cpp [mylib {"profile":"arm-gcc"}]
compiling lib.cpp [mylib {"profile":"mips-gcc"}]
compiling main.cpp [app]
creating libmylib.a [mylib {"profile":"gcc"}]
creating libmylib.a [mylib {"profile":"mips-gcc"}]
creating libmylib.a [mylib {"profile":"arm-gcc"}]
linking app [app]
ERROR: /usr/bin/arm-linux-gnueabihf-g++ -o /home/user/programs/qbs/usr/local/share/qbs/examples/app-and-lib/default/app.7d104347/app /home/user/programs/qbs/usr/local/share/qbs/examples/app-and-lib/default/app.7d104347/3a52ce780950d4d9/main.cpp.o /home/user/programs/qbs/usr/local/share/qbs/examples/app-and-lib/default/mylib.eyJwcm9maWxlIjoiZ2NjIn0-.792f47ec/libmylib.a

ERROR: /home/user/programs/qbs/usr/local/share/qbs/examples/app-and-lib/default/mylib.eyJwcm9maWxlIjoiZ2NjIn0-.792f47ec/libmylib.a: error adding symbols: File format not recognized
collect2: error: ld returned 1 exit status
ERROR: Process failed with exit code 1.
The following products could not be built for configuration default:
app

The build fails only when selecting one profile in the app.qbs file, and this profile should not be the first profile in the qbs.profiles line in the lib.qbs file. 仅当在app.qbs文件中选择一个配置文件时,构建才会失败,并且此配置文件不应是lib.qbs文件中qbs.profiles行中的第一个配置文件。

When selecting two or more profiles - the build succeeds. 选择两个或多个配置文件时-构建成功。

My analysis: 我的分析:

I think this problem is related to multiplexing: 我认为这个问题与多路复用有关:

The lib.qbs contains more than one profile. lib.qbs包含多个配置文件。 This turns on multiplexing when building the library, which, in turn, adds additional ' multiplexConfigurationId ' to the build-directory name ( moduleloader.cpp ). 这将在构建库时打开multiplexConfigurationId ,从而向构建目录名称( moduleloader.cpp )添加附加的“ multiplexConfigurationId ”。

The app.lib contains only one profile, so multiplexing is not turned on and the build-directory name does not get the extra string. app.lib仅包含一个配置文件,因此不会打开多路复用,并且构建目录名称不会获得多余的字符串。

The problem can be solved by changing the code ( moduleloader.cpp ) so that multiplexing is turned even if there is only one profile ie with the following patch: 可以通过更改代码( moduleloader.cpp )来解决该问题,以便即使只有一个配置文件(即具有以下补丁)也可以打开多路复用:

--- moduleloader.cpp    2018-10-24 16:17:43.633527397 +0300
+++ moduleloader.cpp.new    2018-10-24 16:18:27.541370544 +0300
@@ -872,7 +872,7 @@
             = callWithTemporaryBaseModule<const MultiplexInfo>(dummyContext,
                                                                extractMultiplexInfoFromProduct);

-    if (multiplexInfo.table.size() > 1)
+    if (multiplexInfo.table.size() > 0)
         productItem->setProperty(StringConstants::multiplexedProperty(), VariantValue::trueValue());

     VariantValuePtr productNameValue = VariantValue::create(productName);
@@ -891,7 +891,7 @@
         const QString multiplexConfigurationId = multiplexInfo.toIdString(row);
         const VariantValuePtr multiplexConfigurationIdValue
             = VariantValue::create(multiplexConfigurationId);
-        if (multiplexInfo.table.size() > 1 || aggregator) {
+        if (multiplexInfo.table.size() > 0 || aggregator) {
             multiplexConfigurationIdValues.push_back(multiplexConfigurationIdValue);
             item->setProperty(StringConstants::multiplexConfigurationIdProperty(),
                               multiplexConfigurationIdValue);

This worked for my use case. 这适用于我的用例。 I don't know if it make sense in a broader view. 我不知道从更广泛的角度来看是否有意义。

Finally, the questions: 最后,问题是:

Does it all make sense? 这一切有意义吗?

Is this a normal behavior? 这是正常现象吗?

Is this use-case simply not supported? 是否仅不支持该用例?

Is there a better solution? 有更好的解决方案吗?

Thanks in advance. 提前致谢。

Yes, the default behavior with multiplexing is that the a non-multiplexed product depends on all variants of the dependency. 是的,多路复用的默认行为是非多路复用乘积取决于相关性的所有变体。 In general, there is no way for a user to change that behavior, but there should be. 通常,用户无法更改该行为,但应该可以。 However, luckily for you, profiles are special: 但是,幸运的是,配置文件很特殊:

Depends { name: "mylib"; profiles: "arm-gcc" }

This should fix your problem. 这应该可以解决您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM