PDA

View Full Version : moc with same file names?



cjhuitt
26th April 2007, 20:07
I have run into a problem with how qmake generates the targets for moc files, when I have the same file name in different subdirectories.

For instance, in my .pro file, I have the following:


DESTDIR = Objs
MOC_DIR = Mocs
UI_DIR = Uics
RCC_DIR = Rccs

HEADERS += Images/Types.h
HEADERS += Images/Cache.h
HEADERS += Sounds/Types.h
HEADERS += Sounds/Cache.h

SOURCES += Images/Cache.cpp
SOURCES += Sounds/Cache.cpp

CONFIG += warn_on staticlib
TEMPLATE = lib

The Images/Cache.h and Sounds/Cache.h both include class definitions that inherit from QObject in order to provide signals and slots. When I run qmake on the file, it generates the following for the moc targets inside the Makefile:


Mocs/moc_Cache.cpp: Images/Types.h \
Images/Cache.h \
/usr/lib/qt4/bin/moc
/usr/lib/qt4/bin/moc $(DEFINES) $(INCPATH) Images/Cache.h -o Mocs/moc_Cache.cpp

Mocs/moc_Cache.cpp: Sounds/Types.h \
Sounds/Cache.h \
/usr/lib/qt4/bin/moc
/usr/lib/qt4/bin/moc $(DEFINES) $(INCPATH) Sounds/Cache.h -o Mocs/moc_Cache.cpp

This clearly shows a problem, which make warns about when it is run. The moc_Cache.cpp target is generated from two different files. I'm looking for suggestions about whether there might be easy ways to fix the output, or if I need to start having different names for every file in my projects.

Along the way, I did see the "new_moc" example in the qmake advanced configuration section, that would appear to offer a way to fix this, but I was unable to get it to find only the files that should have moc run on them, as opposed to all header files.

wysota
26th April 2007, 20:48
It's best to give those files different names as you'll avoid other problems this way. But you can also divide your project into two subprojects and compile them separately and link together later on.

cjhuitt
26th April 2007, 21:05
It's best to give those files different names as you'll avoid other problems this way.

Just out of curiosity, what other problems might this cause?

It might make a difference to mention that this is a reproduction of a problem I was having on a larger project. In the larger one, each different directory's files, while named the same, had different namespaces to distinguish them in the code. I was hoping to be able to avoid typing


#include "Images/ImagesCache.h"
[...]
{
Images::ImagesCache cache;
[...]
}

And similar items, as the two mentions of "Images" on each line seem redundant. Of course, I could name the class something other than the file name, but on a large project we try to avoid doing that as well.

wysota
26th April 2007, 22:42
Just out of curiosity, what other problems might this cause?
For instance at some point in time you might want to use "-I" options to add include directories to your projects and if you added both directories, one of each dublets would become inaccessible.


It might make a difference to mention that this is a reproduction of a problem I was having on a larger project. In the larger one, each different directory's files, while named the same, had different namespaces to distinguish them in the code. I was hoping to be able to avoid typing


#include "Images/ImagesCache.h"
[...]
{
Images::ImagesCache cache;
[...]
}

Then use -I to avoid having to add directory names in each inclusion and modify filenames of the includes.


And similar items, as the two mentions of "Images" on each line seem redundant. Of course, I could name the class something other than the file name, but on a large project we try to avoid doing that as well.

Use -I (that's INCLUDEPATH option in qmake AFAIR) and modify filenames or provide macros that will include proper files :)

pdolbey
27th April 2007, 10:28
Wouldn't the problem with the generated moc files also propagate to your .o (or my .obj) files when they're compiled into your single "Objs" directory before linking into the lib.

In this "single" libary pattern your total cost of ownership would be minimized by an "ImagesCache.h/cpp" rather than "Images/Cache.h/cpp" model - I then tend to combine all (or at least the public ones) the .h files for a library into a single /inc folder to avoid the worse "Images/ImagesCache.h" folder pattern.

You could still use namespaces to discriminate between same named classes, but I'd probably avoid that as well as it increases subsequent documentation effort , code readability, and re-useability - how many systems have to be patched with "std::" namespace to make them work on different platforms?

Just my 5c.

Pete

cjhuitt
27th April 2007, 14:55
For instance at some point in time you might want to use "-I" options to add include directories to your projects and if you added both directories, one of each dublets would become inaccessible.

You are correct about the include paths, and we have talked about that in my team. Our decision was that, since our older project had a problem with so many files in one directory, we would be splitting them out in multiple subdirectories for our new project. Along with this was the decision to only put the base directories in the include directories options, so that the subdirectory paths would need to be included in order to include the header file. This way, if you were looking at one code file that included another, it would be easier to find the file being included. (Yes, we have had problems with finding the included file. Nothing a find can't solve, but that gets annoying after a while.)

Given that, I was hoping that there was some way to reduce the file names, but I haven't found a simple way to do that yet since the qmake/moc combo presents problems if the files have the same name.

Our current best bet solution is to have multiple subdir project files, until the actual code, but that presents other problems -- namely, not being able to intermix "general" code files in directories that have subdirectories, and generating a lot of smaller library files that will all need to be tracked and linked into the final executable.

cjhuitt
27th April 2007, 15:06
Wouldn't the problem with the generated moc files also propagate to your .o (or my .obj) files when they're compiled into your single "Objs" directory before linking into the lib.

Yes, the current problem propogates to the object files as well; however, if I could find a relatively straightforward way to change the moc file target (turn Images/Cache.cpp into moc_Images_Cache.cpp, for example), the object files would then be unique as well.


In this "single" libary pattern your total cost of ownership would be minimized by an "ImagesCache.h/cpp" rather than "Images/Cache.h/cpp" model - I then tend to combine all (or at least the public ones) the .h files for a library into a single /inc folder to avoid the worse "Images/ImagesCache.h" folder pattern.

As I stated in the above reply (which you couldn't have seen before you wrote this), we decided as a team to break things up into subdirectories to help with the problem of finding files in a few hundred in any given directory, and also of knowing which subdirectory they are in if all you see in a given file is '#include "ImageCache.h"'.


You could still use namespaces to discriminate between same named classes, but I'd probably avoid that as well as it increases subsequent documentation effort , code readability, and re-useability - how many systems have to be patched with "std::" namespace to make them work on different platforms?

Personally, I think that namespaces don't add much to the documentation effort, but increase code understanding (not necessarily readability) and indirectly increase reusability. Using namespaces allows you to know what "area" or "module" of the code something is in, over and above specific classes, which I think helps understanding. Granted, the same could be done by prepending a given part of a name on all related modules, but that is what namespaces are for. As for reusability, if a lot of namespace scoping is going on, it is a warning sign that the code might lack cohesion, and should be re-examined and maybe refactored. Thus, the namespaces indirectly lead to more reusable code.

As for the problem with the std namespace, a significant factor in that was the delayed addition of the namespace to the code headers/compiler enforcement. In this case, since we will be using namespaces from the start of the project, it shouldn't be a problem.

pdolbey
27th April 2007, 17:44
Remember that the original Cache.cpp's have to be compiled as well - the moc files are only generated from the headers - this is where the primary naming conflict comes from.

Pete

cjhuitt
27th April 2007, 19:29
Remember that the original Cache.cpp's have to be compiled as well - the moc files are only generated from the headers - this is where the primary naming conflict comes from.

That's a good point, which I had forgotten about. So, in the end it appears easiest to keep the names different after all.

pdolbey
27th April 2007, 20:36
Well actually I thought about this on the way home. One negative point and one positive.

The negative point is the from a "re-usability" point of view the entire concept of two "cache" objects seems broken anyway - what about generic classes or templates?

However the positive thought was that if you wanted to follow your pattern, then it shouldn't be too difficult to generate your own version of qmake (qmake2) that for a line in the pro file like SOURCES += Images/Cache.cpp forces the compiler directives to emit Images_Cache.o into the Objs folder - this should also work for your moc_ files. After all this is open source...

Pete