Skip to content

Instantly share code, notes, and snippets.

@mishurov
Last active October 7, 2024 18:16
Show Gist options
  • Save mishurov/8134532 to your computer and use it in GitHub Desktop.
Save mishurov/8134532 to your computer and use it in GitHub Desktop.
Makefile to build QT projects (Linux) without qmake
CC=g++
MOC=moc-qt4
CFLAGS=-Wall
SOURCES=hello.cc hello_cls.cc
MOC_HEADERS=hello_cls.h
EXECUTABLE=hello
INCDIRS=-I/usr/include/qt4 -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtCore
LIBS=-lQtCore -lQtGui
# Change postfixes
MOC_SOURCES=$(MOC_HEADERS:.h=.moc.cc)
OBJECTS=$(SOURCES:.cc=.o) $(MOC_SOURCES:.cc=.o)
all: $(EXECUTABLE)
@echo Done!
$(EXECUTABLE): $(OBJECTS)
$(CC) $^ $(LIBS) -o $@
# Generate object files, rule to change postfix
%.o: %.cc
$(CC) $(CFLAGS) $(INCDIRS) -c $< -o $@
# Generate cc from h via Qt's Meta Object Compiler, rule to change postfix
%.moc.cc: %.h
$(MOC) $(INCDIRS) $< -o $@
.PHONY: tags clean
clean:
rm *.o
# Generate ctags file for all included files (autocomplete and jump to source)
tags:
gcc -M $(INCDIRS) $(SOURCES) | \
sed -e 's/[\\ ]/\n/g' | \
sed -e '/^$$/d' -e '/\.o:[ \t]*$$/d' | \
ctags -L - --c++-kinds=+p --fields=+iaS --extra=+q
@a52siddi
Copy link

a52siddi commented Aug 1, 2021

Cool. Could you update it to use with qt5?

it would be cool to have it auto generate the ui_mainwindow.h file too
uic mainwindow.ui -o ui_mainwindow.h

This works for me:

# Based on: 
# - https://www.partow.net/programming/makefile/index.html
# - https://doc.qt.io/qt-5/moc.html
# - https://gist.github.com/mishurov/8134532

CXX      := -c++
MOC      := moc
UIC      := uic
CXXFLAGS := -fPIC
LDFLAGS  := -L/usr/lib/x86_64-linux-gnu -lQt5Quick  -lQt5PrintSupport -lQt5Qml -lQt5Network -lQt5Widgets -lQt5Gui -lQt5Core
BUILD    := ./build
OBJ_DIR  := $(BUILD)/objects
APP_DIR  := $(BUILD)/apps
INC_DIR  := $(BUILD)/include
MOC_DIR  := $(BUILD)/moc
TARGET   := realtimeplot
INCLUDE  := 			\
	-Iinclude/ \
	-I$(INC_DIR) \
	-Iinclude/qcustomplot \
	-I/usr/include/x86_64-linux-gnu/qt5 \
	-I/usr/include/x86_64-linux-gnu/qt5/QtWidgets \
	-I/usr/include/x86_64-linux-gnu/qt5/QtCore \
	-I/usr/include/x86_64-linux-gnu/qt5/QtGui \

SRC      :=                      \
	$(wildcard src/qcustomplot/*.cpp) \
	$(wildcard src/*.cpp)         \

OBJECTS  := $(SRC:%.cpp=$(OBJ_DIR)/%.o)

all: build $(APP_DIR)/$(TARGET)

# mrv: generate ui_mainwindow.h
$(INC_DIR)/ui_mainwindow.h: src/mainwindow.ui
	$(UIC) $< -o $@

# mrv: compile all cpp source files
$(OBJ_DIR)/%.o: %.cpp $(INC_DIR)/ui_mainwindow.h
	@mkdir -p $(@D)
	$(CXX) $(CXXFLAGS) $(INCLUDE) -o $@ -c $<

# mrv: process moc header with Qt's moc utility
# (Qt's signal/slot functionality requires generation of some extra code)
$(MOC_DIR)/moc_mainwindow.cpp: include/mainwindow.h
	$(MOC) $(INCLUDE) $< -o $@

# mrv: process moc header with Qt's moc utility
# (Qt's signal/slot functionality requires generation of some extra code)
$(MOC_DIR)/moc_qcustomplot.cpp: include/qcustomplot/qcustomplot.h
	$(MOC) $(INCLUDE) $< -o $@

# mrv: compile the output of Qt's moc utility
$(OBJ_DIR)/src/moc_mainwindow.o: $(MOC_DIR)/moc_mainwindow.cpp
	@mkdir -p $(@D)
	$(CXX) $(CXXFLAGS) $(INCLUDE) -o $@ -c $<

# mrv: compile the output of Qt's moc utility
$(OBJ_DIR)/src/moc_qcustomplot.o: $(MOC_DIR)/moc_qcustomplot.cpp
	@mkdir -p $(@D)
	$(CXX) $(CXXFLAGS) $(INCLUDE) -o $@ -c $<

# mrv: the order in which the libraries are linked is important!
# mrv: linking libraries must follow the executable and not precede it
$(APP_DIR)/$(TARGET): $(OBJ_DIR)/src/moc_mainwindow.o $(OBJ_DIR)/src/moc_qcustomplot.o $(OBJECTS)
	@mkdir -p $(@D)
	$(CXX) $(CXXFLAGS) $(INCLUDE) $^ -o $@ $(LDFLAGS)

.PHONY: all build clean debug release

build:
	@mkdir -p $(APP_DIR)
	@mkdir -p $(OBJ_DIR)
	@mkdir -p $(INC_DIR)
	@mkdir -p $(MOC_DIR)

debug: CXXFLAGS += -DDEBUG -g
debug: all

release: CXXFLAGS += -O2
release: all

clean:
	-@rm -rvf $(OBJ_DIR)/*
	-@rm -rvf $(APP_DIR)/*
	-@rm -rvf $(INC_DIR)/*
	-@rm -rvf $(MOC_DIR)/*

This was very helpful for me #@mroavi. Thank you 👍

@habaneropep2019
Copy link

This variant is pretty much useless to anyone doing anything modern, but if you're using Qt2 or Osiris (which is my modernized-ish fork of Qt2.3.2), here's a modified version that should work with Qt2 and Osiris. If using Qt2, change $(OSIRISDIR) to $(QTDIR). You'll still need to manually run uic before running make if you're using .ui files.

CC=g++
MOC=moc
CFLAGS=-Wall
SOURCES=main.cpp wizard.cpp
MOC_HEADERS=wizard.h
EXECUTABLE=wizard
INCDIRS=-I$(OSIRISDIR)/include
LIBS=-lqt -L$(OSIRISDIR)/lib
# Change postfixes
MOC_SOURCES=$(MOC_HEADERS:.h=.moc.cc)
OBJECTS=$(SOURCES:.cc=.o) $(MOC_SOURCES:.cc=.o)

all: $(EXECUTABLE)
        @echo Done!

$(EXECUTABLE): $(OBJECTS)
        $(CC) $^ $(INCDIRS) $(LIBS) -o $@

# Generate object files, rule to change postfix
%.o: %.cc
        $(CC) $(CFLAGS) $(INCDIRS) -c $< -o $@

# Generate cc from h via Qt's Meta Object Compiler, rule to change postfix
%.moc.cc: %.h
        $(MOC) $< -o $@

.PHONY: tags clean

clean:
        rm *.o

# Generate ctags file for all included files (autocomplete and jump to source)
tags:
        gcc -M $(INCDIRS) $(SOURCES) | \
        sed -e 's/[\\ ]/\n/g' | \
        sed -e '/^$$/d' -e '/\.o:[ \t]*$$/d' | \
        ctags -L - --c++-kinds=+p --fields=+iaS --extra=+q

@mishurov
Copy link
Author

mishurov commented Aug 7, 2023

@habaneropep2019 it is as old as mammoth shite. I'm working on time series rendered on GPU and QML.

@habaneropep2019
Copy link

@mishurov is there any chance I could get your permission to include your makefile with my Qt fork, under GPLv2 or BSD?

@mishurov
Copy link
Author

mishurov commented Aug 7, 2023

Why even ask that. Sure, of course. I'm not a lawyer. Everything I share, it is for public use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment