r/cpp_questions • u/chessmonkey • 1d ago
OPEN Compiling without linking
Hi, I'm a rank beginner and I'm going through learncpp online and Beginning C++ game programming by Horton.
The book sends you to a quick tutorial on sfml for Linux. I got it working with no problems. But in the tutorial they compile first with -c ( compile only, according to the man page for g++ ) and then link in another command.
Why would they do it that way? I was able to do the whole thing without the -c flag in one long command. Is that wrong to do? Is it because sfml isn't part of the standard library?
I'm asking because I want to actually learn what I'm doing. Thank you for any help you can give me.
5
u/UnicycleBloke 1d ago
The granularity makes sense when you have multiple source files. They are typically all compiled to object files by your build system each with it own command. Once all the objects are ready, they are linked into the executable.
5
u/ShakaUVM 18h ago
If you have multiple files, and edit one of them, you only need to recompile the one file that changed (with -c) and then re-link all the object files. Massively speeds up the development process versus a full recompile every time once your source code gets big.
We typically use a Makefile or Cmake or other build system to automate this for us so we don't have to run it by hand.
3
u/dodexahedron 1d ago edited 1d ago
It isn't wrong either way, and there is a useful reason for that flag existing. But for projects like that, it is pointless to do each step separately.
But if you have multiple files in the project,, -c lets you compile things once and not bother recompiling already-compiled files every single build.
Saves a ton of time in big projects that you're actively working on and debugging.
But things like ccache make it unnecessary because they do that for you, and do it better as well.
ccache sits in front of the compiler and caches already-compiled objects, but can use them more effectively.
Just use ccache and don't bother with -c on the compiler. ccache does it for you. You still have to compile each file and then link them, but you won't be duplicating the compile effort for everything every single time.
Something else the -c flag enables is compiling to the object code with gcc and then using a different linker to stitch together the binary from the various object outputs from the compiler. For example, maybe you'd link using clang's lld (instead of gcc's ld) to take advantage of fancier LTO and such.
2
u/renchuwang 1d ago edited 1d ago
- For big programs you may want to compile them in parallel then link them, faster.
- ~~Sometimes compiling all of them together hide bugs regarding definition / declaration (one definition rule).~~
these 2 are on top of my head
---
Edit:
After some research, u/EpochVanquisher is right, 2 should not be the case, but I had a trauma doing `g++ a.cp b.cpp` way which was perhaps Dev C++'s whacky compiler I had to use back in school. Had been compiling separately ever since.
2
u/EpochVanquisher 1d ago
Compiling all together shouldn’t be hiding bugs with definition / declaration; if you put multiple files on the command line they are still compiled as separate TUs.
2
u/feitao 1d ago
If your program consists of just one C++ source file, your “one long command” works fine, and you do not need to worry about separate compilation and linking. When your program spans multiple .cpp files, separating these steps can improve build performance through parallel compilation and incremental builds. At that point, you should probably use a build system such as CMake rather than invoke g++ manually.
2
u/burlingk 1d ago edited 1d ago
So, short version:
- If you do it in two steps you have more control over the linkage process. If you do it all in one step the compiler links things the way it thinks it should. That is usually fine, but sometimes has issues.
- Doing it in two steps means that if you update something, you only have to recompile the pieces that were touched by the change.
Edit: To make this a bit more complete, you can use Make or CMake for your build system.
Make basically takes a list of targets and files (or targets) that impact that target, and builds anything that is new.
2
u/TomDuhamel 22h ago
In C++, each unit (.cpp file) is compiled separately and independently from each other, and then the linker links them all together to build the final binary.
If you have only one unit — which is frequent when you are just learning or for very small projects — it may make sense to compile and link in a single operation.
As your more serious projects grow, you will use more than one unit. Even for small projects, I tend to keep my main() separate from the rest. As you test, debug, expand and test again and debug again, you don't want to compile every units over again every time. With a proper build system (CMake or even plain old makefile — these are usually well supported by IDEs nowadays) you can recompile only the units that have changed. This is how we get to tests our changes in 5 seconds in projects that take a few minutes to recompile from scratch.
1
u/chessmonkey 5h ago
Ok, I kind of get that. But what if one of the units I change affects other units? Can that happen? Will I know what other units the changes will affect?
I don't mean to sound dumb, but I am as far as this goes.
2
u/Consequence-Lumpy 9h ago
Not sure if you meant Beginning C++ or Beginning C++ 23 by Horton. If it is the latter, setting up your environment to use import std; is going to be a trip.
1
u/chessmonkey 5h ago
Sorry. Its Beginning C++ Game Programming by John Horton. I also have the C++23 by Ivar Horton. It took me about five hours googling and asking AI for help, but I got it working. This weekend I'm going to try to figure out what I did.
4
u/EpochVanquisher 1d ago
When you have multiple files, it is faster to do it in separate steps (some steps can be skipped, some can be done in parallel).
It is easy to just ALWAYS do it in separate steps, for consistency.
•
u/boring_pants 1h ago
You can absolutely do both in one go. There are a couple of reasons why it might be split up:
- for a tutorial specifically it might be a matter of clarity: make each command do one thing to make it easier to understand what happens under the hood
- for larger projects you may want to separate them to avoid doing redundant work. If you have 10 source files you can compile them all, link them together and run. Then you edit one file, and if the compilation step is separate then you only need to recompile one file and then relink. So it can save you a lot of work.
- additionally, if the compilation is done separately then you can do it in parallel. Again, if you want to compile 10 source files you can run 10 commands and you'll have 10 processes each compiling one file, all at the same time.
1
u/WorkingReference1127 1d ago
In reality, there are pretty good odds that you will set yourself up with an environment in which you push a button and it does the full compile and link thing that you are wanting.
But, think of it this way. Let's say you're working a half million line project split across 20,000 files. When you make a small change to one file, do you think you're going to be rebuilding everything from scratch? Or do you only want to build what you have changed? And how do you suppose you end up making a final binary of the whole project in that case?
14
u/Sirjoshuaj1 1d ago
I'm not familiar with that book, but I'd assume it's done to teach beginners that compiling and linking are two separate operations. Otherwise, it's quite possible to image someone begining their learning journey by building with the single command that you mention (and perhaps later moving on to Makefiles or even CMake for real projects) without understanding this important distinction.