2017-08-21 3 views
2

Ich versuche, einige Qt-Projekt zu kompilieren, einschließlich der QCustomPlot-Bibliothek. Als Minimum Beispiel setzte i ein Projekt, bestehend aus:Warum schlägt AUTOMOC fehl, wenn find_package() und qt5_use_modules() aus Funktionen aufgerufen werden?

qcustomplot.h 
qcustomplot.cpp 
CMakeLists.txt 
../cmake/QCustomPlot.cmake 

Das ursprüngliche Projekt ist größer, aber das Problem ist bereits reproduzierbar nur mit den Dateien.

Der CMakeLists.txt enthält diesen Code:

cmake_minimum_required(VERSION 3.6) 

set(CMAKE_AUTOMOC ON) 
include(../cmake/QCustomPlot.cmake) 

function(findqt)          #(1) 
    find_package(Qt5Core) 
    find_package(Qt5Gui) 
    find_package(Qt5Widgets) 
    find_package(Qt5PrintSupport) 
endfunction()           #(1) 

findqt()            #(1) 
#find_package(Qt5Core)         #(2) 

add_library(
    Plots 
    src/qcustomplot.h 
    src/qcustomplot.cpp 
) 


function(linkqt)          #(3) 
    qt5_use_modules(Plots Core Gui Widgets PrintSupport) 
endfunction()           #(3) 
linkqt()            #(3) 

Wenn entweder alle Linien (1) markiert oder alle Linien markiert (3) sind auf Kommentar, die find_package() oder qt5_use_modules() in Dateigültigkeitsbereich bedeutet Aufruf, ich ein Projekt bekommen die zwei qcustomplot enthalten Dateien und eine zusätzliche Plots_automoc.cpp. Die zusätzliche Datei wird automatisch generiert und enthält die erforderlichen und das Projekt kompiliert und verknüpft ordnungsgemäß.

Sobald ich jedoch alle qt-bezogenen Befehle in Funktionen verschiebe, wird die Datei automoc.cpp nicht mehr erzeugt und ist nicht mehr Teil des Projekts, was beim Verknüpfen zu einigen wenigen unresolved external symbol führt.

Der Aufruf eines einzigen find_package() on files-Bereichs (wie Zeile) behebt das Problem und generiert die Automoc-Datei erneut.

Warum ändert das Verschieben der Aufrufe in eine Funktion das Automoc-Verhalten so und wie kann ich erreichen, dass sie immer noch in Funktionen verschoben werden?

Ein wenig Hintergrund: Ich habe bereits einige Ziele in meinem Projekt, erwarte, dass die Zahl schnell wächst und Code-Redundanz vermeiden will. Auch Leute, die nicht wirklich mit CMake trainiert sind, sollen es benutzen. Das ist, warum versuche ich all die Qt bezogene Befehle in Funktionen zu bewegen und einen Befehl wie diesen bieten:

add_my_target(
    targetName 
    SOURCES qcustomplot.h qcustomplot.cpp 
    QT Core Gui Widgets PrintSupport 
    BOOST filesystem 
) 

Mit Ausnahme von Qt, ich dies bereits erreicht ...

Ich habe auch versucht mit

target_link_libraries(${projectName} ${Qt5_Core_LIBRARIES} ... 
//or 
target_link_libraries(${projectName} Qt5::Core ... 

es führt zum gleichen Ergebnis, solange nicht mindestens ein find_package() Anruf direkt auf Dateien Umfang, wird keine automoc erzeugt.

Ich bin mit CMake 3.6.2, Qt 5.7, Visual Studio 2015 und Win 10.

Weiteres Beispiel Olen bekam die meisten meiner zugrunde liegenden Verwirrung mit seiner Antwort aussortiert, aber ein Fall bleibt:

cmake_minimum_required(VERSION 3.6) 
set(CMAKE_AUTOMOC ON) 

function(doit)      #(4) 
    find_package(Qt5Core) 

    add_library(
    Plots 
    qcustomplot.h 
    qcustomplot.cpp 
    ) 

    qt5_use_modules(Plots Core Gui Widgets PrintSupport) 
endfunction()       #(4) 

doit()        #(4) 

Unter Verwendung der mit (4) markierten Linien in eine Funktion all die Erzeugung des Ziels setzen ermöglicht CMake ordnungsgemäß ausgeführt wird, dh qt5_use_modules() definiert ist, in der Lage, alle Module zu finden und verknüpfen sie (zB include, die gesetzt sind richtig ly). Nirgendwo außerhalb der Funktion verlasse ich mich auf Variablen, die von einer der Qt-Funktionen festgelegt wurden. Automoc generiert jedoch nicht die erforderliche CPP-Datei. Durch Kommentieren der markierten Zeilen wird autoc erneut ausgeführt.

Antwort

2

Das Problem ist, dass CMake-Funktionen einen Bereich einführen, so dass die in find_package definierten Variablen außerhalb der Funktion nicht verfügbar sind.

Eine einfache Lösung für Ihr Problem ist die Verwendung von CMake-Makros - Sie können sich diese als CMake-Äquivalent von C-Makros vorstellen. Die dort deklarierten Variablen stehen auch außerhalb des Makrobereichs zur Verfügung.

In Ihrem Fall bedeutet dies, function von macro und endfunction durch endmacro ersetzen.

+0

Für dieses minimale Beispiel könnte Ihre Lösung geeignet sein, aber für das größere Projekt dahinter ist es nicht geeignet. Außerdem kann ich alle 'find_package()' tief in den verschachtelten Funktionen aufrufen und die definierten Variablen wie Qt5_Core_LIBRARIES irgendwo völlig anders benutzen. Nur der AUTOMOC generiert diese einzelne Datei nicht. – Anedar

+0

@Anedar Können Sie in Ihrer Frage angeben, warum ein 'Makro' nicht geeignet ist? – oLen

+0

@Anedar wie für 'Qt5Core_LIBRARIES' noch definiert, habe ich es gerade getestet und die Variablen bleiben nicht definiert, wenn ich eine' Funktion' verwende, was bedeutet, dass meine Antwort in dieser Hinsicht korrekt ist. In Ihrem Fall könnte es wegen des Caches noch da sein oder weil es von woanders kommt. – oLen

Verwandte Themen