77

I want to program using Qt, but I don't want to use special compilers or IDE such as Qt Creator and qmake. I want to write with Kate and compile with g++.

Can I compile a program that uses Qt with g++? How do I compile it with g++?

genpfault
  • 51,148
  • 11
  • 85
  • 139
Squall
  • 4,344
  • 7
  • 37
  • 46
  • 13
    I can understand not wanting to use Qt Creator, but why not use qmake? All qmake does is generate a Makefile for you; if you don't use qmake you'll have to write the same Makefile yourself, and worse you'll have to hand-maintain a different Makefile for each platform you want to compiler under. With qmake you only have to create a single .pro file, instead of having to remember how a MSVC Makefile differs from a gnu Makefile, etc etc. – Jeremy Friesner Sep 02 '10 at 23:45
  • 10
    Because I want to know what happens during compilation instead of using an automatic tool. It is easier with qmake or Qt Creator, but I like to do this task manually. – Squall Sep 03 '10 at 02:36
  • 2
    So you want to write your makefiles manually, instead of using a generator like qmake, cmake or autotools? The only single reason for that is if you want to learn Makefile syntax. The outcome will be a maintenance burden, not portable etc. – Frank Osterfeld Sep 03 '10 at 06:44
  • 5
    You can still look at the Makefile that qmake generates if you want to understand how make works. – Jeremy Friesner Sep 05 '10 at 02:00
  • 8
    There are a lot of us who aren't even using Makefiles - there are other build systems, after all. SCons and bjam, in particular, are very popular. I develop a medium-size client application that has recently started making use of Qt, and there's no way I'm going to switch our whole build system over to qmake - especially when qmake seems to be so flaky when figuring out dependencies and deciding when it must regenerate your Makefiles. – Ted Middleton Apr 15 '13 at 19:59
  • 9
    @JeremyFriesner a better answer (years late) might be: I already have a build tool (make or otherwise) and don't want a library in charge of my toolchain. – Alec Teal Apr 16 '14 at 16:00
  • @JeremyFriesner because I use stuff like `shell find` in my Makefile. How do I use it in .pro files? – Roman Feb 13 '18 at 15:51
  • @Roman You can put a directive like $$system(echo your shell command here) into your .pro file if necessary -- see qmake docs at http://doc.qt.io/qt-5/qmake-function-reference.html – Jeremy Friesner Feb 13 '18 at 17:17
  • This is a solution for Windows, for the same question: https://stackoverflow.com/questions/72774371/how-to-compile-a-qt-program-without-qtcreator-on-windows – Basj Jun 27 '22 at 21:22

5 Answers5

43

Sure you can. Although it is more convenient with qmake or CMake, you can do:

CXXFLAGS += -Ipath_to_your_qt_includes
LDFLAGS += -Lpath_to_your_qt_libs

LDLIBS += -lqt-mt (for Qt3)

or

LDLIBS += -lQtCore -lQtGui (for Qt4, add what you need)

my_prog: my_prog.cpp

(in a makefile)

Update - invoking moc:

Quote from moc manpage:

Here is a useful makefile rule if you only use GNU make:

m%.cpp: %.h
        moc $< -o $@

I'd personally name the output rather %.moc.cpp (than m%.cpp). You then add the dependency of my_prog on my_prog.moc.cpp

my_prog: my_prog.cpp my_prog.moc.cpp

Similarly for uic. The situation here is more complicated, since you have to generate rules for headers and source files, and you have to add a dependency on a header file to ensure it gets generated before the sources are compiled. Something like this might work:

my_prog: my_prog.o my_prog.moc.o my_prog.ui.o
        $(CXX)  $(LDFLAGS) -o my_prog $^ $(LDLIBS)

my_prog.o: my_prog.cpp my_prog.ui.h
jpalecek
  • 47,058
  • 7
  • 102
  • 144
  • 3
    Also, if you use Qt's extended syntax like signals and slots and stuff, you need to run moc manually. That's the only "mandatory" special compiler. – teukkam Sep 02 '10 at 23:45
  • 2
    And this answer doesn't show you how to run `moc` (something that it **sorely** needs to demonstrate) – Ken Bloom Sep 03 '10 at 00:08
23

You certainly don't have to use QtCreator to write a Qt program.

You also don't have to use qmake but you are asking for trouble by not using it.

To do anything even remotely interesting in Qt you will inevitably end up subclassing QObject. All these subclasses require the Q_OBJECT macro in their definition which enables the signal/slot syntax. This syntax is not regular C++ and cannot be compiled using g++. Files containing class definitions with Q_OBJECT must be run through Qt's meta-object compiler which is called moc. This means you have to work out which files need to have moc applied to them, then run moc on them, and then compile the resulting cpp file with g++. This is the reason that Qt supplies qmake. It generates the correct rules in the Makefile for you.

Qt .pro project files are really quite straightforward to work with and I would seriously recommend that you use them. Remember, qmake is a command line tool just like g++. Also, it can actually create a skeleton project file for you by supplying the -project option so to get started you can just do

qmake -project
qmake
make

and you are done. In practice I find that the generated project file may be missing the declaration of any extra Qt libraries I might be using so you might have to add a line like

QT += opengl

if, for example, you have included something like QGLWidget.

feedc0de
  • 3,646
  • 8
  • 30
  • 55
Troubadour
  • 13,334
  • 2
  • 38
  • 57
  • 2
    for all intent and purpose, Qt is pretty useless without QMake. Nice answer. – San Jacinto Sep 03 '10 at 00:13
  • Actually, you can decide to use the .qpp extension for files that need moc'ing. This allows you to create a make rule (or a custom Visual Studio build rule). The generated .cpp file will be compiled normally. – MSalters Sep 03 '10 at 07:59
  • 3
    This answer is misleading. Qmake is a build tool and is independent from moc. You can successfully and easily call moc from a different build tool. I've done this in Visual Studio and SCons for example. In both its easy to have this handled transparently so that you can carry on as normal, as if moc didn't exist. – JBentley Jan 07 '16 at 03:34
  • 1
    @JBentley: The answer makes it quite clear that without `qmake` you would have to "work out which files need to have `moc` applied to them, then run moc on them". I currently work at a company where we have our own build system and it calls `moc` without the help of `qmake`. – Troubadour Mar 02 '16 at 20:07
  • 1
    @Troubadour Yes, but you also said that *"you are asking for trouble by not using [qmake]"*, and that *"I would seriously recommend that you use [.pro project files]"*. I didn't say that your answer was wrong, just misleading. In the context of the question, *"Can I use Qt without qmake or Qt Creator?"*, you imply that it is difficult and/or troublesome to not use qmake. Indeed, the first commenter on the answer concludes that *"Qt is pretty useless without QMake"*. The truth is that qmake is just one of several legitimate and highly useable alternatives. – JBentley Mar 03 '16 at 05:15
  • 4
    "Q_OBJECT...This syntax is not regular C++". It's just a macro and It's perfectly valid C++. All the macro does is declare a bunch of functions. The moc compile provides the definitions. – rfcoder89 Dec 15 '16 at 00:29
  • How does one build a Debug or Release version of the project? – Youda008 Sep 10 '19 at 20:10
7

Here is my makefile for any Qt project without using qmake:

#---------------------------------------------------------------------------------
# Compiler executables
#---------------------------------------------------------------------------------
CC      :=  gcc
CXX     :=  g++

#---------------------------------------------------------------------------------
# Options for code generation
#---------------------------------------------------------------------------------
DEFINES :=  -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED
CFLAGS  :=  -g -Wall $(DEFINES)
CXXFLAGS:=  $(CFLAGS)
LDFLAGS :=  -g -Wl

#---------------------------------------------------------------------------------
# Any extra libraries you wish to link with your project
#---------------------------------------------------------------------------------
LIBS    :=  -lQtGui -lQtCore -lpthread

#---------------------------------------------------------------------------------
# Some more include paths
#---------------------------------------------------------------------------------
INCPATHS:=  -I/usr/share/qt4/mkspecs/default -I/usr/include/QtGui -I/usr/include/QtCore

#---------------------------------------------------------------------------------
# Source folders and executable name
#---------------------------------------------------------------------------------
TARGET  :=  $(shell basename $(CURDIR))
BUILD   :=  build
SOURCES :=  source
INCLUDES:=  source include

#---------------------------------------------------------------------------------
# Source files
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT   :=  $(CURDIR)/$(TARGET)

export VPATH    :=  $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
                    $(foreach dir,$(INCLUDES),$(CURDIR)/$(dir))

CFILES      :=  $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES    :=  $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
HFILES      :=  $(foreach dir,$(INCLUDES),$(notdir $(wildcard $(dir)/*.h)))

#---------------------------------------------------------------------------------
# Use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
    export LD   :=  $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
    export LD   :=  $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

export OFILES   :=  $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(HFILES:.h=.moc.o)

export INCLUDE  :=  $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) $(INCPATHS)

#---------------------------------------------------------------------------------
.PHONY: $(BUILD) clean install uninstall
#------------------------------------------------------------------------------
$(BUILD):
    @[ -d $@ ] || mkdir -p $@
    @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile

#---------------------------------------------------------------------------------
clean:
    @echo clean ...
    @rm -fr $(BUILD) $(TARGET)

#---------------------------------------------------------------------------------
install:
    @cp -u $(TARGET) /usr/bin/$(TARGET)
    @echo installed.

#---------------------------------------------------------------------------------
uninstall:
    @rm -f /usr/bin/$(TARGET)
    @echo uninstalled.

#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
# Makefile targets
#---------------------------------------------------------------------------------
all: $(OUTPUT)

#---------------------------------------------------------------------------------
$(OUTPUT): $(OFILES)
    @echo built ... $(notdir $@)
    @$(LD) $(LDFLAGS) $(OFILES) -o $@ $(LIBS)

#---------------------------------------------------------------------------------
%.o: %.c
#---------------------------------------------------------------------------------
    @echo $(notdir $<)
    @$(C) $(CFLAGS) $(INCLUDE) -c $< -o $@

#---------------------------------------------------------------------------------
%.o: %.cpp
#---------------------------------------------------------------------------------
    @echo $(notdir $<)
    @$(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -o $@

#---------------------------------------------------------------------------------
%.moc.cpp: %.h
#---------------------------------------------------------------------------------
    @echo $(notdir $<)
    @moctool $< $(DEFINES) $(INCLUDE) -o $@

#---------------------------------------------------------------------------------
%.moc.o: %.moc.cpp
#---------------------------------------------------------------------------------
    @echo $(notdir $<)
    @$(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -o $@

#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

Here, moctool is a simple tool that helps for non-QObject headers, here is its source code:

https://github.com/Quent42340/EasyLib/blob/master/tools/moctool/source/main.cpp

Quent42340
  • 71
  • 1
  • 1
  • 1
    I realize this is old, but this answer is _exactly_ what I am trying to do on my current project. However, I'm struggling with understanding a few bits of the logic. First, line 36: `ifneq ($(BUILD),$(notdir $(CURDIR)))` seems to check if the makefile was executed from the build directory, if not it seems to call another `@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile` on line 71. Why? Everything that occurs after the `else` on line 93 starting with the `all:` target is what I would expect, instead. I'm hoping the OP will respond... – ph0t0n Sep 17 '13 at 00:25
0

Some pre-compilers are necessary for Qt projcet, like moc, uic, ...,etc. Qt Creator + qmake are convenient to do such things and generate a makefile for g++ or msvc compilers.

AechoLiu
  • 17,522
  • 9
  • 100
  • 118
0

I like to program with Qt using Vim and reduced version of Qt Designer... this last one helps me to make window prototypes... then i translate the hierarchy from Qt Designer into my handcoded window header on Vim...

The result is that all my code is maintained by myself.. no .ui, no ui_.cpp .. no ui pointer... so i can manipulate my code freely.