-Original Message-
From: Kyle Edwards
Sent: 13 September 2019 16:54
To: Stephen Morris ; cmake@cmake.org
Subject: Re: [CMake] Preventing multiple definitions of metaObject methods
>Stephen,
>Could you post a minimally reproducible example with CMakeLists.txt and
>accompanying source code? I am currently working on a Qt-based >project with
>static libraries and have not encountered this issue.
>Kyle
It appears that the problem was due to a misunderstanding about how the PRIVATE
keyword works in tergat_sources. I'd assumed that it should be used to identify
the 'public headers' of a library (i.e. headers that should be included by the
consumers of that library. It seems that this isn't the case, and even 'public'
headers should be defined with the PRIVATE keyword.
Here are the simple demonstration files I wrote, four in all:
myTest.h
#ifndef MYTEST_HDR
#define MYTEST_HDR
class myTestWindow : public QMainWindow
{
Q_OBJECT
public:
myTestWindow()
virtual ~myTestWindow();
signals:
void readyToDisplay();
private slots:
void showTitle();
};
#endif
myTest.cpp
#include
#include
#include "myTest.h"
myTestWindow::myTestWindow() : QMainWindow(nullptr)
{
// Send the signal when ready to display
(QTimer::singleShot(0, this, ::showTitle));
}
myTestWindow::~myTestWindow()
{}
void myTestWindow::showTitle()
{
setWindowTitle(tr("This is a test window"));
}
#include "moc_myTest.cpp"
main.cpp
#include
#include
#include "myTest.h"
int main(int argc, char *argv[])
{
QApplication * app = new QApplication (argc, argv);
myTestWindow * win = new myTestWindow();
win->show();
app->exec();
return 0;
}
CMakeLists.txt
cmake_minimum_required (VERSION 3.14)
project(myTest LANGUAGES CXX)
find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED PATHS
"C:\\Qt\\5.12.3\\msvc2017_64\\lib\\cmake\\Qt5" NO_DEFAULT_PATH)
set (CMAKE_AUTOMOC ON)
set (CMAKE_AUTORCC ON)
set (CMAKE_AUTOUIC ON)
add_library(myTest_Lib STATIC)
target_sources(myTest_Lib PRIVATE myTest.cpp)
target_sources(myTest_Lib PUBLIC myTest.h)
target_link_libraries(myTest_Lib PUBLIC Qt5::Core Qt5::Widgets)
set_target_properties(myTest_Lib PROPERTIES OUTPUT_NAME myTest)
add_executable(myTest_Exe main.cpp)
target_include_directories(myTest_Exe PRIVATE ${CMAKE_LIST_DIR})
target_link_libraries(myTest_Exe PRIVATE myTest_Lib)
set_target_properties(myTest_Exe PROPERTIES OUTPUT_NAME myTest
VS_DEBUGGER_ENVIRONMENT "PATH=C:\\Qt\\5.12.3\\msvc2017_64\\bin;%PATH%")
Compiling and running them as given here, with the line
"target_sources(myTest_Lib PUBLIC myTest.h)" in the MakeLists.txt file, my
library compiles cleanly but I get an error saying "'QMainWindow': base class
undefined" when trying to compile the executable application. This is because
the compiler encounters the Q_OBJECT macro in myTest.h, generates a new
moc_myTest.cpp, then because it can't see that the original moc_myTest.cpp was
compiled within the library it includes it in its own mocs_compilation.cpp
file. The error occurs when trying to compile this file, since moc_myTest.cpp
does not include anywhere.
If I try to fix this by adding the line "#include " just
above the class declaration in myTest.h, then the error changes to a bunch of
'multiple definition' errors, as I reported in my original question on Friday.
However, if I just change "target_sources(myTest_Lib PUBLIC myTest.h)" to
"target_sources(myTest_Lib PRIVATE myTest.h)", then all the problems go away;
it doesn't even matter whether I leave the redundant '#include' in myTest.h,
everything compiles cleanly either way.
It seems that the matter of static vs. shared libraries in my initial question
was a red herring - in my previous work with shared libraries I haven't used
either the PUBLIC or PRIVATE keywords, but merely supplied add_library with a
list of undifferentiated source files. This problem turns out to have been
entirely a matter of the use of the PUBLIC keyword. I have obviously been using
it incorrectly, though this leads me to wonder what its purpose is, if not for
this.
--
Powered by www.kitware.com
Please keep messages on-topic and check the CMake FAQ at:
http://www.cmake.org/Wiki/CMake_FAQ
Kitware offers various services to support the CMake community. For more
information on each offering, please visit:
CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake