Monday 3 December 2012

Compile Qt Applications with custom Makefile

Hi folks, this is a quick post to "Compile Qt application using your own Makefile".
[ I am sure there is no link which explains about this !!! ]

Stuffs I have used:
[*] Qt 4.8.1 compiled and installed in my machine [how to do that?], with Visual C++ 10 compiler.
[*] Windows-7 operating system, 64-Bit.
[*] Knowledge about writing Makefile [ref] [I am not discussing how to write Makefiles here with this post]

So, our first step is to have one Qt application. For testing purpose you can use mine  [download-in-zip].
In my test application I have used all the stuffs that a common Qt developer needs to, like UI components, CPP files, H files and QRC files.
I will be referring to same test application shared above.

Before I start discussion, let me put all the codes in here first,


/* ----------------------------------------- */
/* File Name: main.cpp        */
/* ----------------------------------------- */
  1. #include <QtGui/QApplication>
  2. #include "mainwindow.h"

  3. int main(int argc, char *argv[])
  4. {
  5.     QApplication a(argc, argv);
  6.     MainWindow w;
  7.     w.show();    
  8.     return a.exec();
  9. }

/* ----------------------------------------- */
/* File Name: mainwindow.cpp        */
/* ----------------------------------------- */
  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include <QPixmap>

  4. MainWindow::MainWindow(QWidget *parent) :
  5.     QMainWindow(parent),
  6.     ui(new Ui::MainWindow)
  7. {
  8.     ui->setupUi(this);
  9. }

  10. MainWindow::~MainWindow()
  11. {
  12.     delete ui;
  13. }

  14. void MainWindow::on_pushButtonShow_clicked()
  15. {
  16.     QPixmap pixmap(":/Image/butterfly.jpg");
  17.     ui->imageLabel->setPixmap(pixmap);
  18. }

/* ----------------------------------------- */
/* File Name: mainwindow.h        */
/* ----------------------------------------- */
  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H

  3. #include <QMainWindow>

  4. namespace Ui {
  5. class MainWindow;
  6. }

  7. class MainWindow : public QMainWindow
  8. {
  9.     Q_OBJECT
  10.     
  11. public:
  12.     explicit MainWindow(QWidget *parent = 0);
  13.     ~MainWindow();
  14.     
  15. private slots:
  16.     void on_pushButtonShow_clicked();

  17. private:
  18.     Ui::MainWindow *ui;
  19. };

  20. #endif // MAINWINDOW_H

And UI file, mainwindow.ui has one QLabel named as "imageLabel" and one QPushButton named, "pushButtonShow".

And QRC file, "TestRsrc.qrc" has butterfly.jpg under one prefix name "/Image".

Now, let's look into Custom Makefiles.

I have divided Makefiles into 2 different parts, with respect to their operation.
First Makefile, under source main directory, defines rules for building Object files.
Second Makefile, under build directory defines rules for linking object files with Qt shared libraries, in general resolves symbol definition in objects.
And, Config file under build directory, as name indicates, has some of the common configuration definitions for compilation.
Below are the Makefiles and Config files,

  1. ####### Config file

  2. CXX           = cl

  3. QT_DEFINES  = -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_GUI_LIB -DQT_CORE_LIB -DQT_HAVE_MMX -DQT_HAVE_3DNOW -DQT_HAVE_SSE -DQT_HAVE_MMXEXT -DQT_HAVE_SSE2 -DQT_THREAD_SUPPORT 

  4. DEFINES       = $(QT_DEFINES) -D"WIN32" -D"WINVER=0x0601" -DINTERNAL -DMEASURE_TIME=0 -DMEASURE_POWER=0 

  5. CXXFLAGS      = -nologo -Zc:wchar_t- -GR -EHsc -MDd -W3 -w34100 -w34189 /Od $(DEFINES) -c

  6. QT_PATH  = C:\QtSDK\Desktop\Qt\4.8.0\msvc2010

  7. INCPATH       = -I"$(QT_PATH)\include" -I"$(QT_PATH)\include\QtCore" -I"$(QT_PATH)\include\QtGui" -I"." -I"..\..\Sources" -I"." -I"$(QT_PATH)\mkspecs\win32-msvc2010" 

  8. LNK           = link.exe

  9. LFLAGS        = /NOLOGO /DEBUG /SUBSYSTEM:WINDOWS /INCREMENTAL:NO 

  10. QT_LIBS       = $(QT_PATH)\lib\qtmaind.lib $(QT_PATH)\lib\QtGuid4.lib $(QT_PATH)\lib\QtCored4.lib 

  11. ADD_LIB  = 

  12. MFLAGS  = -D_MSC_VER=1500 -DWIN32

  13. QMOC  = $(QT_PATH)\bin\moc.exe

  14. QRCC  = $(QT_PATH)\bin\rcc.exe

  15. ####### Output format

  16. PATH_SEP  = ^\
  17. SRCDIR  = ..$(PATH_SEP)
  18. OBJDIR    = .$(PATH_SEP)
  19. OBJECT_SUFIX  = obj
  20. DESTDIR       = .$(PATH_SEP)
  21. TARGET        = TestApp
  22. TARGET_SUFIX  = exe
  23. OUTPUT  = TestApp.$(TARGET_SUFIX)

Makefile, which resides under Build directory,

  1. ####### Makefile for Linking apps #######
  2. ####### Reside under Build directory #######
  3. ####### Basically resolves symbol definitions for objects #######

  4. ####### Includes

  5. include Config
  6. include ..\Makefile

  7. ####### Main Build rules

  8. all: $(OBJECTS) $(TARGET)

  9. $(TARGET): $(OBJECTS) 
  10. $(LNK) $(OBJECTS) $(ADD_LIB) $(QT_LIBS) $(LFLAGS) /out:$(OUTPUT)
  11. clean:
  12. del *.$(OBJECT_SUFIX) *.$(TARGET_SUFIX) moc_*.cpp qrc_*.cpp *.pdb *.manifest 

Makefile, which resides under main source directory,

  1. ####### Makefile for building objects #######
  2. ####### Reside under main source directory #######
  3. ####### Rules and definitions for building objects and other dependencies #######

  4. default:all

  5. ####### Source Files

  6. SOURCES       = $(SRCDIR)main.cpp \
  7. $(SRCDIR)mainwindow.cpp

  8. MOC_SRC  = moc_mainwindow.cpp 
  9. QRC_SRC  = qrc_TestRsrc.cpp
  10. ####### Object Files
  11. CORE_OBJ      = main.$(OBJECT_SUFIX) \
  12. mainwindow.$(OBJECT_SUFIX)

  13. MOC_OBJ  = moc_mainwindow.$(OBJECT_SUFIX)
  14. QRC_OBJ  = qrc_TestRsrc.$(OBJECT_SUFIX)

  15. OBJECTS  = $(MOC_OBJ) $(QRC_OBJ) $(CORE_OBJ)

  16. ####### MOC Source Build rules

  17. moc_mainwindow.cpp: $(SRCDIR)mainwindow.h
  18. $(QMOC) $(DEFINES) $(INCPATH) $(MFLAGS) $(SRCDIR)mainwindow.h -o moc_mainwindow.cpp

  19. ####### QRC Source Build rules

  20. qrc_TestRsrc.cpp: $(SRCDIR)TestRsrc.qrc
  21. $(QRCC) -name TestRsrc $(SRCDIR)TestRsrc.qrc -o qrc_TestRsrc.cpp

  22. ####### Core Object Build rules

  23. main.$(OBJECT_SUFIX): $(SRCDIR)main.cpp
  24. $(CXX) $(SRCDIR)main.cpp $(INCPATH) $(CXXFLAGS) main.$(OBJECT_SUFIX)

  25. mainwindow.$(OBJECT_SUFIX): $(SRCDIR)mainwindow.cpp
  26. $(CXX) $(SRCDIR)mainwindow.cpp $(INCPATH) $(CXXFLAGS) mainwindow.$(OBJECT_SUFIX)
  27. ####### MOC Object Build rules

  28. moc_mainwindow.$(OBJECT_SUFIX): moc_mainwindow.cpp
  29. $(CXX) moc_mainwindow.cpp $(INCPATH) $(CXXFLAGS) moc_mainwindow.$(OBJECT_SUFIX)
  30. ####### QRC Object Build rules

  31. qrc_TestRsrc.$(OBJECT_SUFIX): qrc_TestRsrc.cpp
  32. $(CXX) qrc_TestRsrc.cpp $(INCPATH) $(CXXFLAGS) qrc_TestRsrc.$(OBJECT_SUFIX)

If you have used command line compilation for VC++, by this time you must have understood above Config and Makefiles. I cannot explain command line compilation and other basic stuffs here, but will try to clarify as much as possible.

If you look into Config file,
Line number 3: says compiler we going to use is CL (VC++ command line compiler).
Line number 5: gives some of the Qt standard definitions needed for compilation. -D<definition> or /D<definition> is a flag to define them in CL.
Line number 7: is custom definitions or user definitions. If you have any specific pre-compilation definitions, then you can define them here with flag -D or /D.
Line number 9: is standard CPP and Qt flags used to compile CPP application in CL.
Line number 11: says compiler where to refer for Qt related stuffs compilation. This is where my Qt was installed, you have to change this path to your Qt installation path before you compile.
Line Number 13: is reference path for include files you have used in your application. If you have included any specific files in your program other than mentioned here, you have to include them here.
Line number 15 and 17: says our linking application is link.exe and some standard flags for linking.
Line number 19: says Qt shared libraries (lib files) required to resolve symbols and definitions used in application. If you have referenced any other Qt libraries, for example QtNetwork, you have to include that library here.
Line number 21: is for further development, which gives you option to include and link additional libraries or 3rd party libraries you have referenced in your application.
Line number 23: is flag for generating MOC objects.
Line number 25 and 27: this defines path for moc and rcc apps, which is required to build moc objects and objects out from q-resource files. This apps are part of your Qt installation.
Line 31 to 38 define some of the relative path for where to find elements and output format.

The Makefile under build directory, is quite simple.
It includes definitions and rules from Config and other Makefile. It has 3 rules viz., which builds Objects first and then Target exe will be linked with libs and objects. These are the general Makefile rules I have used and nothing much to say about them.

Now, let me brief some about Makefile under main source directory.
This Makefile contains basic rules to build objects out from standard CPP files, MOC files and QRC files.
Remember steps to build the objects,
> MOC objects and QRC objects should be built before you build CPP objects.
> Header files (.h files), having Q_OBJECT macro definition in their class, needs only be generated MOC files. Other header files can be treated as normal CPP headers.
> Before you build MOC and QRC objects, you have to use moc.exe and rcc.exe apps to build their corresponding CPP files.
So look into Makefile, Line number 9, 12 and 14 says we have 4 CPP source files need to be compiled into Objects.
Line number 25 says we have 3 types of objects, need to be built in order specified.
If you look into Moc source build rules, that is line number 29 and 30, it uses moc.exe app to generate moc_mainwindow.cpp source file corresponding header "mainwindow.h". To know more about building Moc objects in Qt, refer here.
Line number 34 and 35 says standard rules to build QRC source file.
Refer naming conventions for building Moc and QRC files; they have moc_<filename>.cpp and qrc_<filename>.cpp; and their corresponding object files will be moc_<filename>.obj and qrc_<filename>.obj after built. This is how it has to be, and follow the same convention for better understanding.
At this point we have all 4 source files ready to build into objects. Use CPP standard method to build all source files into objects. Don't forget to specify proper paths for your build.

That is all about your custom Makefiles, used to build your Qt application.

If you have downloaded my sample application, which I have shared above, try to build it with Visual C++ command line.
Unzip the file into safe location (say c:\testapp)
Open Config file, inside build directory, with any text editor and change "Qt_PATH" definition to corresponding Qt installation path in your machine.
Go to Start > All Programs > Microsoft Visual Studio 2010 > Visual Studio Tools, and open "Visual Studio Command Prompt 2010".
Navigate to the location c:\testapp and then navigate inside "build" directory.
Give command "nmake all"
This should build your exe. In order to run the exe, you have to keep corresponding runtime DLLs inside the directory where exe is executing from. So copy two files QtCored4.dll and QtGuid4.dll from your Qt installation path into build directory and run the application.
To clen the build, execute command "nmake clean".

Hope this is helpful.

No comments:

Post a Comment