代码之家  ›  专栏  ›  技术社区  ›  jpo38

使用并行生成时,pre-targeteps失败

  •  1
  • jpo38  · 技术社区  · 6 年前

    我正在使用自定义资源管理(代替qrc),并尝试将其集成到qtcreaor。

    我有一个python脚本,它生成要编译的源文件。我用 QMAKE_EXTRA_TARGETS / PRE_TARGETDEPS 告诉 QMake

    CONFIG += ordered
    
    generated_file.target   = my_custom_target
    generated_file.commands = echo "Generating..." && d:/dev/vobs_ext_2015/tools_ext/python/Python34_light/python.exe $$PWD/pyc_res_generator.py -o $$PWD/generated/generated.cpp && echo "Generated!"
    generated_file.depends  = FORCE
    
    QMAKE_EXTRA_TARGETS            += generated_file
    
    PRE_TARGETDEPS                 += my_custom_target
    
    SOURCES                        += generated/generated.cpp
    
    #DEPENDPATH = ./generated
    

    pyc_res_generator.py 简单地说:

    #! /usr/bin/env python
    # -*- coding: utf8 *-*
    
    import argparse
    
    parser = argparse.ArgumentParser(description="", formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("-o", type=str, help="Output file name")
    
    args = parser.parse_args()
    
    with open(args.o, 'w') as output_file:
        output_file.write( "// This is valid C++!" )
    

    为了测试这一点,我在泛型.CPP中编写了一些无效的C++。 fjkfkfk )当我编译(目标是Android)时,我在日志中看到:

    echo Generating... && python.exe pyc_res_generator.py -o generated/generated.cpp && echo Generated!
    Generating... 
    B:\Android\android-ndk-r11b/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++ -c -Wno-psabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -DANDROID -Wa,--noexecstack -fno-builtin-memmove -std=c++11 -g -g -marm -O0 -fno-omit-frame-pointer -Wall -Wno-psabi -W -D_REENTRANT -fPIC -DQT_QML_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I..\TestQt -I. -IB:\QtCreator5_6_1\5.6\android_armv7\include -IB:\QtCreator5_6_1\5.6\android_armv7\include\QtWidgets -IB:\QtCreator5_6_1\5.6\android_armv7\include\QtGui -IB:\QtCreator5_6_1\5.6\android_armv7\include\QtCore -I. -isystem B:\Android\android-ndk-r11b\sources\cxx-stl\gnu-libstdc++\4.9\include -isystem B:\Android\android-ndk-r11b\sources\cxx-stl\gnu-libstdc++\4.9\libs\armeabi-v7a\include -isystem B:\Android\android-ndk-r11b\platforms\android-9\arch-arm\usr\include -IB:\QtCreator5_6_1\5.6\android_armv7\mkspecs\android-g++ -o main.obj ..\TestQt\main.cpp
    B:\Android\android-ndk-r11b/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++ -c -Wno-psabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -DANDROID -Wa,--noexecstack -fno-builtin-memmove -std=c++11 -g -g -marm -O0 -fno-omit-frame-pointer -Wall -Wno-psabi -W -D_REENTRANT -fPIC -DQT_QML_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I..\TestQt -I. -IB:\QtCreator5_6_1\5.6\android_armv7\include -IB:\QtCreator5_6_1\5.6\android_armv7\include\QtWidgets -IB:\QtCreator5_6_1\5.6\android_armv7\include\QtGui -IB:\QtCreator5_6_1\5.6\android_armv7\include\QtCore -I. -isystem B:\Android\android-ndk-r11b\sources\cxx-stl\gnu-libstdc++\4.9\include -isystem B:\Android\android-ndk-r11b\sources\cxx-stl\gnu-libstdc++\4.9\libs\armeabi-v7a\include -isystem B:\Android\android-ndk-r11b\platforms\android-9\arch-arm\usr\include -IB:\QtCreator5_6_1\5.6\android_armv7\mkspecs\android-g++ -o dialog.obj ..\TestQt\dialog.cpp
    B:\Android\android-ndk-r11b/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++ -c -Wno-psabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -DANDROID -Wa,--noexecstack -fno-builtin-memmove -std=c++11 -g -g -marm -O0 -fno-omit-frame-pointer -Wall -Wno-psabi -W -D_REENTRANT -fPIC -DQT_QML_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I..\TestQt -I. -IB:\QtCreator5_6_1\5.6\android_armv7\include -IB:\QtCreator5_6_1\5.6\android_armv7\include\QtWidgets -IB:\QtCreator5_6_1\5.6\android_armv7\include\QtGui -IB:\QtCreator5_6_1\5.6\android_armv7\include\QtCore -I. -isystem B:\Android\android-ndk-r11b\sources\cxx-stl\gnu-libstdc++\4.9\include -isystem B:\Android\android-ndk-r11b\sources\cxx-stl\gnu-libstdc++\4.9\libs\armeabi-v7a\include -isystem B:\Android\android-ndk-r11b\platforms\android-9\arch-arm\usr\include -IB:\QtCreator5_6_1\5.6\android_armv7\mkspecs\android-g++ -o generated.obj ..\TestQt\generated\generated.cpp
    B:\QtCreator5_6_1\5.6\android_armv7\bin\moc.exe -DQT_QML_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -IB:/QtCreator5_6_1/5.6/android_armv7/mkspecs/android-g++ -IC:/Users/jp225611/Documents/TestQt -IB:/QtCreator5_6_1/5.6/android_armv7/include -IB:/QtCreator5_6_1/5.6/android_armv7/include/QtWidgets -IB:/QtCreator5_6_1/5.6/android_armv7/include/QtGui -IB:/QtCreator5_6_1/5.6/android_armv7/include/QtCore -I. -IB:\Android\android-ndk-r11b/sources/cxx-stl/gnu-libstdc++/4.9/include -IB:\Android\android-ndk-r11b/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include -IB:\Android\android-ndk-r11b/platforms/android-9/arch-arm//usr/include ..\TestQt\dialog.h -o moc_dialog.cpp
    ..\TestQt\generated\generated.cpp:1:1: error: 'fjkfkfk' does not name a type
       // This is valid C++!
       ^
    makefile:670: recipe for target 'generated.obj' failed
    mingw32-make: *** [generated.obj] Error 1
    mingw32-make: *** Waiting for unfinished jobs....
    Generated!
    13:59:08: Le processus "B:\QtCreator5_6_1\Tools\mingw492_32\bin\mingw32-make.exe" s'est terminé avec le code 2.
    Erreur lors de la compilation/déploiement du projet TestQt (kit : android_armeabi-v7a)
    When executing step "Make"
    13:59:08: Temps écoulé : 00:03.
    

    我看到了 generated\generated.cpp 由正确生成 Pyc-Res-Generator.py(Pyc-Res-Generator.py) (现在包含 // This is valid C++! )…但显然是太晚了,就像编译器看到的那样 FJKKFK型 … 如您所见,输出报告:

    Generating...
    B:\Android\android-ndk-r11b/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++ .... ..\TestQt\generated\generated.cpp
    Generated...
    

    虽然人们希望:

    Generating...
    Generated...
    B:\Android\android-ndk-r11b/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++ .... ..\TestQt\generated\generated.cpp
    

    这仅在启用并行生成时发生(我设置 MAKEFLAGS 环境变量到'-j8`)

    它看起来像我的自定义命令 generated_file 在之前启动 生成的\生成的.cpp 已编译,但系统不会在实际编译之前等待它结束。 生成的\生成的.cpp .

    我做错什么了吗?

    3 回复  |  直到 6 年前
        1
  •  1
  •   jpo38    6 年前

    PRE_TARGETDEPS (自定义目标)不是这里的好方法,因为 generated_file.target 必须与makefile目标名称完全匹配,该名称可能因不同选项而异:

    • 是否启用卷影生成
    • 主机平台(使用斜杠或反斜杠作为文件夹分隔符)
    • 可能是目标编译器/平台

    然而,自定义编译器显然工作得更好。Moccing文件就是这样完成的。自定义编译器可以生成一个要编译的新文件(然后系统在编译之前等待生成该文件,即使在执行并行编译时也是如此)。

    # Set fuiles to be generated in a variable
    TO_GENERATE = $$PWD/generated/generated.cpp
    
    # Specify custom command output file:
    custom_generator.output  = $$PWD/generated/generated.cpp
    # Specify custom command:
    custom_generator.commands = 'echo "Generating..." && python $$PWD/pyc_res_generator.py -o $$PWD/generated/generated.cpp && echo "Generated..."'
    # dependency:
    custom_generator.depends = FORCE
    # link to input file variable
    custom_generator.input = TO_GENERATE
    # link to variable to store generated file to
    custom_generator.variable_out = SOURCES
    # add to qmake:
    QMAKE_EXTRA_COMPILERS += custom_generator
    

    那么,您甚至不需要指定 SOURCES += $$PWD/generated/generated.cpp . 而且, $$PWD/generated/generated.cpp 清理后删除!

    这完全符合预期!

        2
  •  0
  •   Thomas    6 年前

    您需要将目标的名称设置为它生成的文件的名称。以下是一个适合我的完整项目文件(qmake 3.1,qt 5.10.1):

    # Filename relative to the *build* directory.
    generated_file.target   = generated/generated.cpp
    generated_file.commands = 'echo "Generating..." && mkdir -p generated && echo "int main() {}" > generated/generated.cpp'
    generated_file.depends  = FORCE
    
    QMAKE_EXTRA_TARGETS     += generated_file
    
    # Filename relative to the *source* directory.
    SOURCES                 += $$OUT_PWD/generated/generated.cpp
    

    原因是 generated_file.target 成为目标的名称 Makefile ,所以什么时候 generated.cpp 如果需要,将执行自定义规则以创建文件。

    您也可以将其从 PRE_TARGETDEPS ,因为您已经将生成的文件添加到 SOURCES instead 从而创建适当的依赖关系。

    建造 目录,而不是 来源 目录。这就是为什么您需要指定 $$OUT_PWD SOURCES :默认情况下,qmake似乎假定 来源 是相对于源目录的。

    如果您想在 来源 相反,您可能认为您只是前缀 $$PWD 但是qmake有时使用绝对路径,有时使用相对路径,而一切都失败了。你也许可以用它来解决这个问题 $$absolute_path($$PWD) 但我没试过。

    生成的 生成文件 (评论是我的):

    # How to create generated/generated.cpp.
    # Depending on FORCE to make it always stale (fails if you create a file named FORCE :)).
    generated/generated.cpp: FORCE
        echo "Generating..." && mkdir -p generated && echo "int main() {}" > generated/generated.cpp
    
    # generated.o depends on generated/generated.cpp.
    # Note that it's not in the same directory; we don't care.
    generated.o: generated/generated.cpp 
        $(CXX) -c $(CXXFLAGS) $(INCPATH) -o generated.o generated/generated.cpp
    
    # The final executable depends on the compiled generated.o.
    OBJECTS = generated.o
    $(TARGET):  $(OBJECTS)  
        $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
    

    这个 qmake documentation 只是说得很含糊 target 应为“自定义生成目标的名称”。但是,该示例显示,他们正在将其设置为输出文件的名称。(作为奖励,它还显示了如何在 commands )

        3
  •  0
  •   Rumex    5 年前

    另一种方法是在并行构建环境中使用template=subdirs来支持libname.depends。每个应用程序文件夹中都需要两个.pro文件。以及共享库文件夹中的一个。开发区域中使用template=subdirs的任何其他文件夹都需要保持兼容。

    例如testapp使用liblarry。

    testapp文件夹有 bld.pro和testapp.pro。

    测试程序:

    #This is a TEMPLATE=subdirs, which gmake will interpret;  
    # making sure the build dependencies are respected
    TEMPLATE = subdirs
    SUBDIRS += bld  mylib
    bld.file = bld.pro
    bld.depends = mylib # force library to be built first.
    mylib.file = $${PATH_TO_LIB_LARRY}/liblarry.pro
    

    专业建筑:

    TARGET=TestApp
    SOURCES+=TestApp.cpp
    PRE_TARGETDEPS+=$${PATH_TO_LIB_LARRY}/liblarry.a
    
    #boilerplate...
    QT -= gui
    CONFIG = ...
    include ($${PATH_TO_LIB_LARRY}/liblarry.pri) # contains include file info
    CONFIG += link_prl # allow lib larry to specify its position in the linker input command.
    

    Librarry拥有的文件夹 利布拉里专业版 包含

    librarry.pro:我是一名职业选手。

    TARGET=larry
    TEMPLATE=lib
    CONFIG+=staticlib 
    CONFIG+=create_prl # export information, so apps can link correctly
    SOURCES+=my_shared_function.cpp
    include (liblarry.pri)
    

    利布拉里.pri:

    HEADERS += $$PWD/my_shared_function.h
    INCLUDEPATH += $$PWD