Pregunta

La versión 5.0 de QT ha traído un conjunto de comandos más fáciles para construir proyectos QT utilizando CMAKE. Consulte http://qt-project.org/doc/qt-5/ Ctake-manual.html . Los recursos para un proyecto deben incluirse utilizando el comando qt5_add_resources .

Si mi archivo de recursos se nombra, por ejemplo, icon32.qrc, el comando qt5_add_resources (recursos icon32.qrc) lo convertirá automáticamente en un archivo qrc_icon32.cpp y definirá Una $ {Recursos} variable que luego podré incluir en los objetivos adecuados.

Hacer esto funciona perfectamente, , excepto que obtengo un error de compilación en CDASH aproximadamente una vez cada 20 construye . El error es típicamente de la siguiente forma:

/.../CMake/build/qrc_Icon32.cpp:272380:1: error: unknown type name 'qCleanupResources_Icon32'

Lo que está sucediendo es que se repite una parte variable de la última línea del archivo qrc_icon32.cpp después de lo que normalmente debe ser el final del archivo, creando así una última línea nonsensal para el compilador. < / p>

Registro ¿Qué hace CMake, parece que el comportamiento de qt5_add_resources es lo siguiente: siempre que llegue a un proyecto que requiera los recursos en cuestión, ejecuta un depende Archivo que es específico para el objetivo de compilación, pero eso todavía escribiría el qrc_icon32.cpp en la raíz del directorio de compilación , y esto para todos los objetivos. Entonces, si se están compilando dos objetivos en paralelo, dos invocaciones de rcc podrían estar escribiendo en el mismo archivo al mismo tiempo, de ahí la corrupción.

No he encontrado ningún informe / discusión de este problema / característica en la web, así que me pregunto si podría haber perdido algo:

¿Hay una manera de decirle a Cmake para guardar el qrc_icon32.cpp generado en una ubicación diferente para cada objetivo? Mejor aún, ¿es posible decirle a Cmake que llame rcc solo una vez desde su principal archivo make para que qrc_icon32.cpp esté disponible más tarde para todos los objetivos?

Supongo que una solución sería crear una biblioteca estática que sea la única que usa $ {recursos} y luego vincular esa biblioteca en todos los objetivos. Pero aún así, creo que Ctake debería poder administrar sus dependencias correctamente al compilar con la bandera multithreading -J.


Para reproducir el problema, en una carpeta vacía, cree un cmakelist.txt que contiene el siguiente

CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11)
PROJECT(SSCCE CXX)

set(CMAKE_PREFIX_PATH /usr/local/Qt-5.3.0 ${CMAKE_PREFIX_PATH})

set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

INCLUDE_DIRECTORIES(SYSTEM "/usr/local/Qt-5.3.0/include/QtCore")
find_package(Qt5Core REQUIRED)
QT5_ADD_RESOURCES(RESOURCES Icon32.qrc)

SET(LIBLIST gobject-2.0 X11-xcb Xi xcb-render-util SM ICE xcb-glx xcb-render xcb-atom xcb-property xcb-event dbus-1 xcb xcb-image xcb-icccm xcb-sync xcb-xfixes xcb-shm xcb-randr xcb-shape xcb-keysyms fontconfig freetype Xrender Xext X11 jpeg png Qt5::Core z m dl gthread-2.0 rt glib-2.0 GL pthread)

ADD_EXECUTABLE(FirstTarget Main1.cpp ${RESOURCES})
TARGET_LINK_LIBRARIES(FirstTarget ${LIBLIST})
ADD_EXECUTABLE(SecondTarget Main2.cpp ${RESOURCES})
TARGET_LINK_LIBRARIES(SecondTarget ${LIBLIST})

luego main1.cpp y main2.cpp se crean usando

#include <iostream>

using namespace std;

int main(int argc, char** argv) {
        std::cout<<"Hello World 1"<<std::endl;
        return 0;
}

El archivo QRC es

<RCC>
    <qresource prefix="/">
        <file>Icon32/YourImage.png</file>
    </qresource>
</RCC>

Luego, cree una carpeta llamada ICON32 y agregue una imagen PNG de su nombre de elección YourImage.png.

Finalmente, cree un directorio de compilación, ingrese y ejecute:

cmake -DCMAKE_CXX_COMPILER=g++-4.8 -DCMAKE_CXX_FLAGS='-std=c++11 -fPIE' ..
make -j2

La salida debe ser algo así como

Scanning dependencies of target FirstTarget_automoc
Scanning dependencies of target SecondTarget_automoc
[ 10%] [ 20%] Automoc for target FirstTarget
Automoc for target SecondTarget
[ 20%] [ 20%] Built target FirstTarget_automoc
Built target SecondTarget_automoc
[ 30%] [ 40%] Generating qrc_Icon32.cpp
Generating qrc_Icon32.cpp
Scanning dependencies of target SecondTarget
Scanning dependencies of target FirstTarget
[ 50%] [ 60%] Building CXX object CMakeFiles/SecondTarget.dir/Main2.cpp.o
Building CXX object CMakeFiles/FirstTarget.dir/Main1.cpp.o
[ 70%] [ 80%] Building CXX object CMakeFiles/SecondTarget.dir/qrc_Icon32.cpp.o
Building CXX object CMakeFiles/FirstTarget.dir/qrc_Icon32.cpp.o
[ 90%] [100%] Building CXX object CMakeFiles/SecondTarget.dir /SecondTarget_automoc.cpp.o
Building CXX object CMakeFiles/FirstTarget.dir/FirstTarget_automoc.cpp.o
Linking CXX executable SecondTarget
Linking CXX executable FirstTarget

Puede ver que QRC_ICON32.CPP se crea dos veces aproximadamente al mismo tiempo, en la raíz del directorio de compilación. Los archivos QRC_ICON32.CPP.O se crean correctamente en el firstTARGET.DIR y SCIDTARGET.DIR, por lo que no hay conflictos.

Mi punto es ese: 1) QRC_ICON32.CPP debe crearse en FIRSTTARGET.DIR y SCIDTARGET.DIR también o 2) Debe crearse en la raíz del directorio de compilación, pero solo una vez para todos los objetivos.

¿Fue útil?

Solución

qt5_add_resources escribe el archivo en CMAKE_CURRENT_BINARY_DIR, no CMAKE_BINARY_DIR

https://qt.gitoriaus. org / qt / qtbase / fuente / d953d9a4c3bdc5ed3b8d380c4b893b51b523bc50: src / corelib / qt5coremacros.ctake # l205

DITTO QT 4:

http://cmake.org/gitweb?p=CMAKE.GIT;A=BLOB ;f=modules/QT4Macros.cMake ;H=B1B12D68B07AAC076719C681FB844F4F98BE8151;HB=HEAD#L21212

Actualización:

Con el código fuente que proporcionó en su actualización, es posible ver el problema.

http://www.cmake.org/pipermail/cmake/ 2008-octubre / 024492.html

http://cmake.org/gitweb?p= Ctake.git; a= commitdiff; h= 0ECE8F79

http://public.kitware.com/bug/view.php? id= 12311

La solución es agregar un objetivo personalizado y agregar explícito depende de eso.

cmake_minimum_required(VERSION 2.8.11)

project(MyTest)

find_package(Qt5Core)

qt5_add_resources(RSCS somefile.qrc)
add_custom_target(gen_qrc DEPENDS ${RSCS})

add_executable(foo foo.cpp ${RSCS})
add_dependencies(foo gen_qrc)
add_executable(bar bar.cpp ${RSCS})
add_dependencies(bar gen_qrc)

CMAKE 3.0 tiene una característica de Autorcc:

http:// www. cmake.org/cmake/help/v3.0/manual/cmake-qt.7.html#autorcc

También pone el archivo QRC_ generado en el directorio de compilación actual. Cmake 3.1 lo pondrá en un directorio específico de destino, lo que hará que este problema desaparezca:

http://cmake.org/gitweb?p= cmake.git; a= commitdiff; h= 33774ca2

Otros consejos

El comportamiento reportado se debe al hecho de que qt5_add_resources se llama al principio en el proceso, durante la configuración y antes de que se inicie realmente la compilación. En este punto, la variable $ {Ctake_current_binary_dir} apuntada por Steveire se define como la la carpeta de construcción de raíces . (Esto se puede probar fácilmente agregando un mensaje ( de salida en qt5coremacros.cmake .

El resultado de la función qt5_add_resources es crear comandos personalizados que se llamarán durante el proceso de compilación: https://qt.gitorious.org/qt.gitorious.org/qt /qtbase/source/d953d9a4c3bdc5ed3b8d380c4b893b51b523bc50%3asrc/corelib/qt5coremacros.cmake#l231

Si se definen múltiples objetivos, entonces esos comandos personalizados podrían ser llamados más tarde en paralelo al mismo tiempo. En ese momento, el $ {Outfile} no se redefinirá utilizando el entonces actual $ {cpake_current_binary_dir} y, por lo tanto, los procesos paralelos escribirán en el mismo archivo en la raíz de la directorio de compilación.

Mirando el código para qt5_add_resources No parece estar disponible para corregir ese comportamiento en caso de compilación multithread, sin embargo, como se señala por Steveire, la solución para la función de comando personalizada subyacente También se puede aplicar con éxito.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top