Re: [CMake] Preventing multiple definitions of metaObject methods

2019-09-16 Thread Stephen Morris
-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


Re: [CMake] Preventing multiple definitions of metaObject methods

2019-09-16 Thread Stephen Morris
-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

Thank you Kyle. I created a basic example as you suggested - a simple 
application linking a simple static library, both incorporating a header 
containing Q_OBJECT - and to my great chagrin it worked perfectly, without any 
compilation errors. 

So it seems that I've been wrong to suspect this as the cause of the 
multiple-definition errors in my main project. Clearly I must dig deeper, and 
if I find that the final explanation is of general interest then I shall report 
back.

Stephen.
-- 

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


Re: [CMake] Preventing multiple definitions of metaObject methods

2019-09-13 Thread Kyle Edwards via CMake
On Fri, 2019-09-13 at 15:25 +, Stephen Morris wrote:
> Suppose I have a class that derives from QObject, and contains the
> Q_OBJECT macro in its header file. When I compile it using AUTOMOC
> enabled, a "moc_myClass.cpp" file is created; if I manually include
> that file at the end of my 'myClass.cpp" file, then the moc file will
> be compiled there, otherwise CMake will take matters into its own
> hands and compile it anyway.
> 
> Now suppose make my class into a static library. The static library
> now contains the object code generated when moc_myClass.cpp was
> compiled.
> 
> I now include my static library from an application. Unless I enable
> AUTOMOC again, then I get a compilation error when Q_OBJECT is
> encountered. If I do enable it, then CMake generates a new
> moc_myClass.cpp file and, since it can't see the place where it was
> included in myClass.cpp, it goes ahead and recompiles it, placing the
> object code alongside the application's other object code.
> 
> Now, when the application links in the static library, it finds two
> definitions of moc_myClass.cpp's object code, and gives a multiple
> definition error.
> 
> All the ways I've come up with so far to work around this are so
> hacky that I'm embarrassed to mention them. There must be a proper
> way to handle this situation. Please can someone advise me what it
> is?
> 
> (N.B. I've been doing this for years with dynamic libraries are never
> encountered a problem, presumably because there the application
> doesn't get to see the inner workings of the library's object code.
> This issue does seem to be specific to static libraries, of which I
> have little prior experience).

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
-- 

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