PDA

View Full Version : QMake Preventing UI_HEADERS_DIR from being added to include path



extronus
22nd August 2010, 07:03
Hi,

I have a mid scale project which i recently decided to move from lumbering netbeans to qtcreator and change the build system to qmake. It consists of a core library, a gui library, various tests and executables.

Directory structure goes like this



libcore
string.h
signal.h
a.h
b.h
a.cpp
b.cpp
libgui
widget_a.h
widget_a.cpp
form_a.ui
form_a.h
form_a.cpp
form_b.ui
form_b.h
form_b.cpp
tests and executables
test directory
test_a.h
test_a.cpp
executable directory
exe_a.h
exe_a.cpp


As you can see, i have some header names like "string.h" and "signal.h" and because of that, when a library is built, it is supposed to go into build directory like this.



build_direcotory
include
tbs
string.h
signal.h
widget_a.h
ui_widget_a.h // Generated as result of uic causes directory
// to be added to include path
etc...
lib
libcore.a


To achieve this, i have an pri file and a function in it. (macro / test ?)
which does configuration _almost_ correctly



# ----------------------------------------------------------------------------
header_copy.input = HEADERS
header_copy.commands = @$$QMAKE_COPY ${QMAKE_FILE_NAME} ${QMAKE_FILE_OUT}
header_copy.output = ../include/tbs/${QMAKE_FILE_BASE}.h

# ----------------------------------------------------------------------------
defineTest(configuration) {
target_name = $$1
target_type = $$2
output_directory = $$3

TARGET = $$target_name
INCLUDEPATH = $$output_directory/include
LIBS += -L$$output_directory/lib

contains(target_type, lib) {
TEMPLATE = lib
CONFIG += staticlib
DESTDIR = $$output_directory/lib
UI_DIR = $$output_directory/obj/ui
#UI_HEADERS_DIR = $$output_directory/include/tbs
QMAKE_EXTRA_COMPILERS += header_copy
}
else:contains(target_type, exe) {
DESTDIR = $$output_directory/bin
TEMPLATE = app
debug {
CONFIG += console
}
}

export(TARGET)
export(TEMPLATE)
export(CONFIG)
export(DESTDIR)
export(UI_DIR)
export(UI_HEADERS_DIR)
export(INCLUDEPATH)
export(LIBS)
export(HEADERS)
export(QMAKE_EXTRA_COMPILERS)
}


Which is called from each "pro" file like this


include (../tbs_desktop.pri)
configuration(tbs, lib, ..)


This does most of the job as intended. However the commented out line which places generated headers to their correct place, also adds that directory to include path. Resulting headers like "string.h" and "signal.h" to be included from standart library and Qt in place of intended headers. Creating a thousand lines long compile time mess. :)

I've tried :



INCLUDEPATH -= $$UI_HEADERS_DIR

which had no effect, and attempted to replace command that executes uic with



# ----------------------------------------------------------------------------
UIC.input = FORMS
UIC.commands = @$$QMAKE_UIC ${QMAKE_FILE_NAME} -o ../include/tbs/${QMAKE_FILE_BASE}.h && echo ehore
UIC.output = ../include/tbs/${QMAKE_FILE_BASE}.h
QMAKE_EXTRA_COMPILERS += UIC


but this created another mess.

Is there a way to prevent UI_HEADERS_DIR from being added to include path or any other way to work around this issue?

* autotools is not an option as it is not really cross platform. (it requires a full blown unix environment to work)
* CMake is an option but it requires re-write of build system and i'm a total newbie to it.

tbscope
22nd August 2010, 07:39
Do I understand you right that you want to have a separate build dir?
If so, use OBJECTS_DIR = ... in your .pro file.

extronus
22nd August 2010, 07:51
Do I understand you right that you want to have a separate build dir?
Uh.. no. I'm already building in to a seperate dir. I just want to prevent the direcotry pointed by UI_HEADERS_DIR to being added to INCLUDEPATH.

tbscope
22nd August 2010, 08:02
Sorry for asking stupid questions, but I don't understand your problem.
Are you trying to build separate targets? Why do you want to copy headers?

Edit: well, I do understand what your problem is, but not why.

extronus
22nd August 2010, 08:48
As i said, i have two types of libraries, core and gui. Let's say core library (libtbs) has a signal class resides in "signal.h" and "signal.cpp" both are in "source/libtbs" directory. To use signal class from within signal.cpp or any other file within core library i'm including it like #include "signal.h"

That's ok. But when i need to use signal class from one of the unit tests or from a gui library, #include "signal.h" will not work. Since they are not in the same directory. Adding "source/libtbs" to include path (-I../libtbs) will not work either as "signal.h" from libtbs and "signal.h" of POSIX will be included in place of each other... So, the headers of libtbs must be copied to "builddir/include/tbs" and "builddir/include" must be added to include path then users of core library can include and use "signal.h" as #include <tbs/signal.h>

Setting UI_HEADERS_DIR to builddir/include/tbs also enables -I builddir/include/tbs causing "signal.h" of core library to be included in place of POSIX one.

squidge
22nd August 2010, 08:57
Wouldn't it be easier to just rename your signal.h to tbs_signal.h ? Then you have no collisions to worry about and can just use the paths as normal without copying header files around.

extronus
22nd August 2010, 09:11
It is. However this will move signal.h from it's own _namespace_ to global one. ( #include <tbs/signal.h> | #include <tbs_signal.h> ) breaking source consistency with previous versions etc... Isn't it correct way to shape the build system for project instead of shaping the project for build system?

extronus
23rd August 2010, 19:13
I've managed to solve the problem by overriding uic.

The key point is disabling the uic by adding "CONFIG -= uic" then using a custom compiler. I'm posting both full configuration file and another that uses it.

pri file.



# Public domain.
# Turns off warnings about strict aliasing
QMAKE_CXXFLAGS += -Wstrict-aliasing=0 -Wno-unused-parameter
CONFIG += no_include_pwd silent
CONFIG -= uic

# ----------------------------------------------------------------------------
# Header copier
header_copy.input = HEADERS
header_copy.CONFIG += no_link target_predeps
header_copy.variable_out = GENERATED_FILES

# ----------------------------------------------------------------------------
# UI compiler
tbsuic.input = FORMS
tbsuic.variable_out = GENERATED_FILES
tbsuic.CONFIG += no_link target_predeps

# ----------------------------------------------------------------------------
defineTest(configuration) {
target_name = $$1
target_type = $$2
output_directory = $$3

TARGET = $$target_name
INCLUDEPATH = $$output_directory/include
LIBS += -L$$output_directory/lib
UI_DIR = $$output_directory/obj/ui
UI_HEADERS_DIR = $$output_directory/include/tbs
QMAKE_EXTRA_COMPILERS += tbsuic header_copy

# Relative part of header _compiler_
header_copy.output = $$output_directory/include/tbs/${QMAKE_FILE_BASE}.h
header_copy.commands = @$$QMAKE_COPY ${QMAKE_FILE_NAME} ${QMAKE_FILE_OUT}

# Relative part of ui compiler
tbsuic.output = $$output_directory/include/tbs/ui_${QMAKE_FILE_BASE}.h
tbsuic.commands = @$$QMAKE_UIC ${QMAKE_FILE_NAME} -o $$output_directory/include/tbs/ui_${QMAKE_FILE_BASE}.h

contains(target_type, lib) {
TEMPLATE = lib
CONFIG += staticlib
DESTDIR = $$output_directory/lib
}
else:contains(target_type, exe) {
DESTDIR = $$output_directory/bin
TEMPLATE = app
debug {
CONFIG += console
}
}

export(TARGET)
export(TEMPLATE)
export(CONFIG)
export(DESTDIR)
export(UI_DIR)
export(UI_HEADERS_DIR)
export(INCLUDEPATH)
export(LIBS)
export(HEADERS)
export(header_copy.output)
export(header_copy.commands)
export(tbsuic.output)
export(tbsuic.commands)
export(QMAKE_EXTRA_COMPILERS)
}



Pro file that uses configuration file


include (../tbs_desktop.pri) #Inclusion

#First parameter is target's name, second is it's type, and third is source root relative
#to project
configuration(tbs_forms, lib, ..)

SOURCES += \
point_list_model.cpp \
tabular_data_editor.cpp \
route_editor.cpp \
.....

HEADERS += \
vertex.h \
tabular_data_editor.h \
route_editor.h \
point_list_model.h \
...

FORMS += \
route_editor.ui \
line_property_editor.ui \
.....



"CONFIG -= uic" is suggested at irc.freenode.net#qt by someone which his/her nick name is
eluding my memory at the moment. :)