3

I have a game with two separate projects for the application itself and the tests. I'm building all of the projects in-source. Here's a shortened version of my project structure:

game
    game.pro
    app
        app.pro
        Entity.h
        Entity.cpp
        Entity.o
        moc_Entity.cpp
        moc_Entity.o
    tests
        layer
            layer.pro
            Entity.o (duplicated)
            moc_Entity.cpp (duplicated)
            moc_Entity.o (duplicated)
            tst_Layer.cpp

app.pro:

QT += core gui

greaterThan(QT_MAJOR_VERSION, 4) {
    QT += widgets
}

TARGET = cotw-clone
TEMPLATE = app

MOC_DIR = .moc
OBJECTS_DIR = .obj

HEADERS += MainWindow.h \
    Map.h \
    Tile.h \
    Character.h \
    Layer.h \
    NewGameDialog.h \
    GameController.h \
    Stair.h \
    Random.h \
    MapGenerator.h \
    TileData.h \
    Statistics.h \
    StatisticsDialog.h \
    StatisticWidget.h \
    Range.h \
    Level.h \
    RandomMapGenerator.h \
    AiController.h \
    MonsterJournalWidget.h \
    InventoryDialog.h \
    PathSearch.h \
    PathNode.h \
    Path.h \
    Geometry.h \
    EntityDatabase.h \
    EntityData.h \
    Entity.h \
    CharacterData.h \
    EntityMetadata.h

SOURCES +=\
    MainWindow.cpp \
    Map.cpp \
    Tile.cpp \
    Character.cpp \
    Layer.cpp \
    NewGameDialog.cpp \
    GameController.cpp \
    Stair.cpp \
    TileData.cpp \
    Statistics.cpp \
    StatisticsDialog.cpp \
    StatisticWidget.cpp \
    Level.cpp \
    RandomMapGenerator.cpp \
    AiController.cpp \
    MonsterJournalWidget.cpp \
    InventoryDialog.cpp \
    PathSearch.cpp \
    PathNode.cpp \
    Path.cpp \
    EntityDatabase.cpp \
    EntityData.cpp \
    Entity.cpp \
    CharacterData.cpp \
    main.cpp

FORMS += MainWindow.ui \
    NewGameDialog.ui \
    StatisticsDialog.ui \
    StatisticWidget.ui \
    MonsterJournalWidget.ui \
    InventoryDialog.ui

RESOURCES += \
    icons/icons.qrc \
    tiles/tiles.qrc

RESOURCES += \
    entities/entities.qrc

My problem is that all of the tests projects use classes from the app project, which means they're compiling all of these classes even though they've already been compiled when app was built. Take the layer test project, for example:

layer.pro:

QT += testlib
QT -= gui

greaterThan(QT_MAJOR_VERSION, 4) {
    QT += widgets
}

TARGET = tst_LayerTest
CONFIG += console
CONFIG -= app_bundle

TEMPLATE = app

SOURCES += tst_LayerTest.cpp
DEFINES += SRCDIR=\\\"$$PWD/\\\"

HEADERS += "../../app/Entity.h"
SOURCES += "../../app/Entity.cpp"

So how can I point qmake to the .o (and qrc_, .moc etc.) files that have already been produced in app? Is there some qmake variable for this purpose, or is my project structure just fundamentally flawed?

Mitch
  • 23,716
  • 9
  • 83
  • 122
  • It looks like [this](http://stackoverflow.com/questions/4644643/how-to-add-object-files-to-a-project-in-qt) answers my question, but am interested to know if there's an easier way than specifying each `.obj` file. – Mitch Dec 09 '12 at 13:13
  • Does [this answer, using wildcard *](http://stackoverflow.com/a/9464075/104370) help? – Clare Macrae Dec 09 '12 at 13:42
  • I had thought about doing that, but was unsure of what would happen with regards to `.o` files that would get linked but not used.. would that slow down my build significantly? – Mitch Dec 09 '12 at 13:54
  • It's hard to say, with the amount of info supplied, but I doubt it. Why not just try it, and see if it works? – Clare Macrae Dec 09 '12 at 14:23
  • It works fine, except that the wildcard includes `main.o`, which causes multiple definitions of `'main'` to be found. Is there a way to exclude certain files or patterns? – Mitch Dec 09 '12 at 15:13
  • Sure. I've added an answer, with an example of how to do that. – Clare Macrae Dec 09 '12 at 18:12

1 Answers1

2

You can use wildcards in qmake .pro files, to save having to maintain a list of all file names.

For example,

SOURCES += *.cpp

Each time you run qmake, that pattern *.cpp gets expanded in to the current list of files matching the pattern.

You can also use -= to remove file names, if you have a particular filename that you wish to exclude.

For example:

SOURCES += *.cpp
SOURCES -= main.cpp

Edit

I almost suggested in my earlier answer that you introduce a library, using qt's lib template, to contain your common code.

Then your build structure would look like this - assuming that you can move files around, from app/ to lib/:

game
    game.pro
    app
        app.pro
        main.cpp
    lib
        lib.pro
        Entity.h
        Entity.cpp
        Entity.o
        moc_Entity.cpp
        moc_Entity.o
    tests
        layer
            layer.pro
            tst_Layer.cpp

You can find some info on library projects in "Building a Library" on the Qt website

If, for some reason, you can't move your files around, then you can introduce a new directory for the library, and have it pull in source files from the app directory - but that is definitely more faff, and more confusing:

game
    game.pro
    app
        app.pro - builds only main.o
        main.cpp
        Entity.h
        Entity.cpp
        moc_Entity.cpp
    lib
        lib.pro
        Entity.o
        moc_Entity.o
    tests
        layer
            layer.pro
            tst_Layer.cpp

Edit 2

One problem you have is you are putting object files in to the LIBS variable, which defines what libraries your code will link against. So that'll be why you are getting errors with those files.

Try changing those LIBS uses to OBJECTS instead, and it may work.

If not, have a read of this thread, which is asking pretty much the same thing.

In particular, see the answer by ChrisW67 of '13th May 2012, 10:14' which begins;

Try:

OBJECTS += f1.o f2.o f3.o f3.o

although I think that, if you have the source, building it into your app directly or via a library is a better option.

Clare Macrae
  • 3,670
  • 2
  • 31
  • 45
  • A-ha! That would make sense. Thanks. :) – Mitch Dec 10 '12 at 22:04
  • Note that you have to have `app` listed before `tests` in `game.pro`, otherwise the build will fail, as the `.o` files it depends on from `app` will not yet be generated. – Mitch Dec 10 '12 at 22:25
  • Hmm.. `LIBS += "../../app/.obj/*.o" LIBS -= "../../app/.obj/main.o"` still gives me `multiple definition of 'main'`. – Mitch Dec 10 '12 at 22:34
  • I'm confused. You didn't mention LIBS before. Please could you add a complete .pro file to your quesiotns, so that we can understand what you are trying to achieve? – Clare Macrae Dec 10 '12 at 22:59
  • Sorry, I've added `app.pro` to my question. I'd rather not create a separate library if I an avoid it, but it might come to it. – Mitch Dec 11 '12 at 18:24
  • I get the error when building any project which links to the `.o` files, e.g.: http://pastebin.com/vz8PrhJR – Mitch Dec 11 '12 at 18:31
  • I just ended up using a library; much easier. :p Thanks. – Mitch Dec 12 '12 at 21:29