From my experience if you have problems like the binary being 3 times larger when utilizing CMake you need to look at the complete build process.
First check if the compiler/linker options are really same: Using CMake with GNU Make: How can I see the exact commands?
If they all match you can - to find out what sections are actually larger - compare the map files of your output in the CMake and non-CMake case. In CMake you need to add -Wl,-Map=<TARGET_NAME>.map
to your linker flags. How to add linker flags see: CMake: How to set the LDFLAGS in CMakeLists.txt?
Or alternatively use nm
or size
on your a.out
: Tool to analyze size of ELF sections and symbol
Last you try activating other optimization options of your linker (the generic -O
option should be supported even by older compilers). See also: Remove useless files, includes, global variables and functions in C++
.c
vs .o
and GNU on Windows
There should not be a difference between giving the source files or the object files to gcc
. But if you're using the GNU toolchain on Windows you may have been stumbled across a workaround in Windows-GNU.cmake:
# The gcc/collect2/ld toolchain does not use response files
# internally so we cannot pass long object lists. Instead pass
# the object file list in a response file to the archiver to put
# them in a temporary archive. Hand the archive to the linker.
This workaround does result in:
gcc a.c -o a.c.o
gcc b.c -o b.c.o
gcc c.c -o c.c.o
rm objects.a
ar cr a.c.o b.c.o c.c.o -o objects.a
gcc objects.a -o a.out
The problem is the ar
call in the middle. If CMake would take the .o
files directly you would be fine.
You can overwrite this workaround by setting CMAKE_C_LINK_EXECUTABLE
back to its default after your project()
command:
set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
Additional reference: CMake: use a custom linker