I'm making a program (let's call it ProgramWP) made with Qt 4.8.5 on a Fedora and based on a QWizard structure with its QWizardPages. The program has more or less 50 classes, 30 of them are QWizardPages.
The thing is that the program executable 'weights' (dunno the english word/expression) 8Mb ( the release version) and I want to know:
Why does it weight so much? Which is the cause?
How can I reduce it?
I need to reduce it because in the product of the enterprise, there are some applications runing, some of them mine. To sup up the exe's:
ProgramMAIN (1.5MiB): the main program of the enterprise.
ProgramMAIN2(600KiB): another important program of the enterprise.
ProgramWP(8MiB): My main program (made with Qt).
ProgramMINI(2.5Mib): My mini version of my main program (made with Qt).
Program3(1.3MiB): My other program made with Qt
As you can see my main program weights so so so much than the main one while the main one is soooo much bigger (ProgramWP is just a little program to configure some easy things).
I'm linking statically some of our libs in ProgramWP and ProgramMINI but so does programMAIn and ProgramMAIN2 so... knowing that ProgramMain2 is 600Kibs with the linked libraries, my ProgramWP should not weight more than that.
This is how I do the linking in the .pro file:
unix:!macx: LIBS += -L$PWD/../../ConfigLib/Release/ -lLib1
INCLUDEPATH += $PWD/../../Lib1
DEPENDPATH += $PWD/../../Libs/Release
unix:!macx: PRE_TARGETDEPS += $PWD/../../Libs/Release/Lib1.a
I've searched and asked and found that I could add the QMAKE_CXX_FLAGS+= -s line to the .pro file to delete the unnecesary symbolsand after doing it and runing the qmake, it stills weight the same (It's like if it was ignored). I've see if gcc uses the -s param and rebuilding I get:
g++ -c -pipe -std=c++11 -s -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_SCRIPT_LIB -DQT_XML_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/lib/qt4/mkspecs/linux-g++ -I../MyProject-I/usr/include/QtCore -I/usr/include/QtNetwork -I/usr/include/QtGui -I/usr/include/QtXml -I/usr/include/QtScript -I/usr/include -I../../Utils -I../../Lib1-I../../Lib2-I../../Lib3-I../../Lib4-I. -I. -I../MyProject-I. -o wp2.o ../MyProject/wpmine.cpp
so as you can see, seems that gcc uses that param so... Any idea of why is it so heavy and how can I fix it?
Thank you so much.
Note: Their programs are made with eclipse and c++ basically while mine is made with Qt. To run it they have isntalled some Qt libraries in the enterprise's product so another question is... could they run my program without that libraries installed? Just putting there the exe and calling it?
Here are some tips to reduce executable size:
You might want to use strip on your executable (in case something went wrong with compiler's -s flag)
Compiling with -Os flag might reduce executable size slightly
Reducing size of the data segment of the executable. Note that every constant (including string literals, static arrays initializers, etc) is stored inside executable and increases it's size:
const char* str = "A very very long string"; // will bloat your executable
BigDataType myData[] = { ... }; // will bloat your executable
Moving embedded resources into external files (or even to the network). Embedded icons, images, strings, etc.) increase binary size dramatically. See QtResource
Reduce usage of the templated code. Massive use of templates (along with their instantiation) is a well known reason of code bloating. This is a trade-off between code size and code beauty.
You might want to try CopperSpice, a fork of Qt, if it does any better.
Related
I'm currently writing a game in C++ using SDL on Ubuntu. I recently multithreaded my engine, so I switched from profiling with valgrind/callgrind to gperftools. I have gotten it to work, but it will not print my own function names. Oddly enough, it recognizes SDL function names (I've seen the reverse happening on a few threads online; shared library functions not having their names found).
kcachegrind Output
I run my program, and the execute the following two commands in order to get this:
pprof --callgrind /bin/ls ls.prof > ls.callgrind
kcachegrind ls.callgrind
I know there are several ways to use gperftools; I have done it by including "gperftools/profiler.h" and using the ProfilerStart("ls.prof") and ProfilerStop() functions.
For reference, here is part of my Makefile in case that is relevant:
OBJS = background.o gameObject.o uGrid.o main.o Timer.o sdlHandlers.o player.o handleEvents.o handleAllStateChanges.o enactAllStateChanges.o cleanLoop.o renderAll.o loadAllFiles.o loop.o inputHandler.o loopWrite.o loopDebug.o loopDebugSingleStep.o loopDebug_SDLDecoupled.o
CC = g++
CFLAGS = -std=c++11 -Wall -O3 -c -g
Aegis: $(OBJS)
$(CC) $(OBJS) -I/sdlLib -lSDL2 -I/sdlLib -lSDL2_image -I/sdlLib -lSDL2_mixer -lX11 -pthread -lprofiler -o Aegis
I removed all references to object files and the like; this is not the entire file. Upon request, I can post the entire Makefile.
Also, because people have gotten confused in the past, I AM using a copy of the SDl2 libraries in my project's folder. That is not a typo.
If anything is unclear, I am happy to answer or provide more source code if needed. Anything to get this problem fixed
Thanks!
You seem to be linking your program without debug symbols. Add -g (or I tend to add -ggdb3) to flags.
I am using mingw 64 bit with cygwin.
I know that if I compile using
x86_64-w64-mingw32-g++.exe -std=c++11 hello.cpp
the output .exe does not run unless the library path to libstdc++ and other libraries is specified in the Path environment variable.
An alternative is to link statically
x86_64-w64-mingw32-g++.exe -std=c++11 hello.cpp -static-libgcc -Wl,-Bstatic -lstdc++ -lpthread
Since I want a single .exe that I can easily copy on different machines, the second solution is better for me. My only problem is that, since I link statically, even for a simple helloworld program, the size of the executable rises to more than 10 Mb. So my question is: is it possible to link statically only the library parts that are actually used by the program?
The binutils linker on Windows, ld, does not support the --gc-sections argument properly, which in combination with compiler flags -ffunction-sections and -fdata-sections, allow the linker to throw away blocks of unused code.
You are straight out of luck. The only thing you can do is the usual: strip the executable (by running the strip command on it after it is linked) and compile your code optimising for size with -Os.
Keeping in mind these options do not work on Windows (which for the purpose of this answer, includes the Cygwin platform), this is generally how you can do this:
g++ -c -Os -ffunction-sections -fdata-sections some_file.cpp -o some_file.o
g++ -c -Os -ffunction-sections -fdata-sections main.cpp -o main.o
g++ -Wl,--gc-sections main.o some_file.p -o my_executable
I have a vexing C++ problem. I've got a huge, complex wedge of code which is compiled into a Linux shared object. When it goes through one specific code path, it segfaults. (Basically one of the STL iterators seems to point a few bytes to the side of where it should.) But, if I #include all the code into one giant source file and compile it into a stand-alone program, everything works perfectly.
How do I even begin to debug this? The problem appears to not be a source-level problem, but (I guess?) some kind of weird linker issue. I'm completely lost. (I thought STL was all compile-time stuff...)
In case it matters, the SO is compiled like so:
g++ -m64 -c -D_CONSOLE -D__UNICODE__ -fPIC -O0 -g -D_DEBUG -D_GLIBCXX_DEBUG <name> -o <name>.o
g++ -m64 -shared -o MangoLib.so <objects...>
The stand-alone consists of a small driver program with a bunch of #include directives, built like so:
g++ -m64 -fPIC -O0 -g -D_DEBUG -D_GLIBCXX_DEBUG Test.cpp -o Test
I don't think I did anything wrong here... but the SO segfaults every single time, so I guess I did? I don't know what to do now.
I would start to check the usage of global variables and static initializers. The order of these things happening is not well defined AFAIK. Every global variable or static initializer that more complicated than "just fill this memory with 0 bits" should be suspect. Several static initializers referencing each other is basically a no go.
Qt generates a .cpp file when compiling the resource, e.g. images, which are defined in the .qrc file. The compile output is as follows:
/usr/local/Qt-5.5.1/bin/rcc -name images ../myApplication/images.qrc -o qrc_images.cpp
g++ -c -pipe -g -std=c++0x -Wall -W -D_REENTRANT -fPIC -DQT_QML_DEBUG -DQT_DECLARATIVE_DEBUG -DQT_QUICK_LIB -DQT_MULTIMEDIA_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_SQL_LIB -DQT_CORE_LIB -I../myApplication -I. -I../shared_base/Debug -I../shared_base -I/usr/local/Qt-5.5.1/include -I/usr/local/Qt-5.5.1/include/QtQuick -I/usr/local/Qt-5.5.1/include/QtMultimedia -I/usr/local/Qt-5.5.1/include/QtGui -I/usr/local/Qt-5.5.1/include/QtQml -I/usr/local/Qt-5.5.1/include/QtNetwork -I/usr/local/Qt-5.5.1/include/QtSql -I/usr/local/Qt-5.5.1/include/QtCore -I. -I/usr/local/Qt-5.5.1/mkspecs/linux-g++ -o qrc_images.o qrc_images.cpp
So as seen in the output, to compile the image resources, two different commands are executed, the rcc and the g++.
However, one can simply compile the images with the rcc and register this binary file in the application during run time. I can't understand what this g++ command does and why it is necessary.
Also why does qt include libs such as Multimedia, Gui, etc. into this file and make it larger than just the images?
Note: The images folder is sized 27MB. The generated images.cpp file is sized 66MB and if I compile the images with the rcc-utility myself it is also 27MB and it works just like the 66MB did.
...one can simply compile the "images" with the rcc and register this
binary file in the application during run time.
As #vahancho pointed out, Qt resources can be loaded dynamically too if you generate a binary resource data with -binary option of rcc. That file can be loaded with QResource::registerResource() function.
I can't understand what this g++ command does and why it is necessary.
It builds the object file, which is then linked into the binary at a later stage.
Also why does qt include libs such as Multimedia, Gui etc into this
file and make it larger than just the images?
Including the libs doesn't necessary mean the binary will be larger. Linker will produce a binary only with those objects that are used in your code.
The cpp file generated by rcc is bigger, because every byte in images will become 0x00 code in cpp.
If your file is 100KB, the cpp file may be 500KB, it's ok.
The final executable file will not so big, binary is binary, cpp is cpp.
I'm trying to build a self contained executable, which I can run on any/most linux host.
I know I can do that with containers, but for now I'm trying to just statically link my exe.
I compile with:
g++ -std=c++1y -fopenmp -Ofast -g -march=x86-64 -mtune=generic -m64 -c <source>.cpp -MMD -MP -o <object>.o
And link with:
g++ -std=c++1y -fopenmp -Ofast -g -march=x86-64 -mtune=generic -m64 <list of object files> <list of absolute path to static libs .a> -lpthread -static-libgcc -static-libstdc++ -o exe
It used to work just fine, but I just discovered it now breaks on some hosts with
error while loading shared libraries: libmvec.so.1: cannot open shared object file: No such file or directory
I don't know if it's something in the code or system libraries update. I have tried (to no avail):
removing -fopenmp
adding -lmvec -lm to the linker
My exe is indeed statically linked: ldd exe says not a dynamic executable. But it insists on loading libmvec.so at runtime: strace exe says:
execv
a bunch of mmap
open(ld-linux-x86-64.so), read it and close it
open(ld.so.cache), stat, mmap, and close it
open(libpthread.so), read, stat, mmap and close it
open(libmvec.so) => fail on hosts where it doesn't exist
[...]
As I understand libmvec is an extension of libm, dealing with x86 vectorization, used by OpenMP.
So basically, I'm asking if there is a way to make it work statically - I see at least 3 solutions:
disable its use - but that would probably mean performance loss, plus it is used even when I disable OpenMP
statically link it, and somehow explain to the runtime that it then doesn't have to dynamically link to it since it's already linked.
make it optional, i.e. dynamically select a slower code path if it's not available. This sounds complex but could in theory be possible.