Story / scenario opener
You clone a repository from GitHub, run make, and the terminal immediately stops with gcc: command not found. You install gcc, run the build again, and now it complains about missing headers or a broken linker. You are trying to compile software from source, but your Fedora installation only ships with runtime libraries. The build toolchain is missing.
What is actually happening
Compiling C or C++ code requires a coordinated set of programs. The preprocessor expands macros and includes header files. The compiler translates source files into assembly. The assembler converts that into object code. The linker stitches everything together with the standard library and resolves external symbols. A build system like make or cmake orchestrates the steps and tracks file dependencies. Fedora keeps the default desktop and server images lean by excluding these tools. They live in package groups instead of the base system. The @development-tools group is a curated collection that installs the compiler, standard libraries, archivers, debuggers, and build orchestrators in one transaction. You do not need to hunt down individual packages. The group handles the dependency graph for you.
Run dnf group list hidden to see every available group on your system. The Development Tools group is marked as default in the repository metadata, which means dnf knows exactly which packages belong together. The package manager resolves hidden dependencies like binutils, glibc-devel, and libstdc++-devel automatically. You get a working toolchain without manually tracking version compatibility.
Install the toolchain
Run the group install command to pull in the complete C and C++ build environment.
sudo dnf groupinstall "Development Tools"
# -y automatically answers yes to the transaction prompt
# groupinstall pulls the entire curated set instead of a single package
# Fedora resolves all hidden dependencies like binutils and glibc-devel
The transaction will list roughly two hundred packages. Read the summary before confirming if you removed the -y flag. The package manager will download the compiler, the C++ standard library, make, cmake, git, autoconf, and automake. It will also pull in gdb for debugging and strace for system call tracing. Everything lands in /usr/bin and /usr/lib. The headers for the standard C library go to /usr/include. You do not need to configure paths manually. The compiler finds them automatically.
Fedora follows a strict separation between user configuration and package files. Configuration files live in /etc/. Package binaries and libraries live in /usr/lib/ and /usr/bin/. Never edit files in /usr/lib/. Your changes will vanish the next time dnf updates the package. Edit /etc/ when you need to override defaults. The package manager tracks /etc/ files and prompts you to merge changes during upgrades. Trust the package manager. Manual file edits drift, snapshots stay.
Verify the installation
Confirm that the core binaries are present and report the correct version.
gcc --version
# Prints the GCC version and target architecture
# Confirms the C compiler binary is in your PATH
g++ --version
# Verifies the C++ frontend is installed alongside gcc
make --version
# Checks that the build orchestrator is ready to read Makefiles
The output will show the version number, the target triplet, and the copyright notice. If all three commands return a version string without errors, the toolchain is operational. Compile a trivial test file to prove the linker and standard library work together.
echo '#include <stdio.h>
int main() { printf("Build OK\n"); return 0; }' > test.c
gcc test.c -o test_binary
# Compiles the C source into an executable
# Links against libc automatically
./test_binary
# Runs the binary to confirm dynamic linking works
The terminal should print Build OK. If it prints that, the compiler, linker, and runtime libraries are correctly wired. Delete the test files afterward. Keep your working directory clean. Run make clean in real projects to remove object files and executables before rebuilding. Stale object files cause cryptic linker errors later.
Common pitfalls and what the error looks like
The toolchain installs correctly, but source builds still fail. The missing piece is usually a third-party library header. Fedora splits runtime libraries and development headers into separate packages. The runtime package provides the .so files your program needs to run. The -devel package provides the .h headers and pkg-config metadata your compiler needs to build against the library.
When you try to compile a project that depends on libcurl, the compiler stops with this exact error:
fatal error: curl/curl.h: No such file or directory
compilation terminated.
The fix is to install the development package for that specific library.
sudo dnf install libcurl-devel
# -devel packages ship headers and pkg-config files
# The compiler uses pkg-config to find include and link flags
# Runtime libraries are already installed on a standard Fedora system
Another common failure is a missing pkg-config definition. The build system runs pkg-config --cflags --libs openssl and gets a non-zero exit code. The terminal prints Package openssl was not found in the pkg-config search path. Install openssl-devel to resolve it. Always check the project's README or INSTALL file for the exact -devel package names. Fedora follows the upstream naming convention. The library name matches the -devel suffix.
C++ standard version mismatches also break builds. Modern projects require C++17 or C++20. The default compiler flags might target an older standard. The build fails with error: 'optional' is not a member of 'std'. Pass the correct flag to the compiler or set it in your environment.
export CXXFLAGS="-std=c++20"
# Tells g++ to use the C++20 standard library features
# Many modern CMake projects read this variable automatically
# Override it per-project if the upstream Makefile hardcodes flags
SELinux occasionally blocks builds that try to write to restricted directories or execute scripts in /tmp. The build script fails silently or prints a generic permission denied message. Check the audit log before disabling the security module.
sudo journalctl -t setroubleshoot | tail -n 5
# Reads the SELinux denial summaries
# Shows exactly which process was blocked and why
# Run this before touching setenforce or SELinux config files
The log will show a one-line summary with a boolean or file context fix. Apply the suggested command. Do not switch SELinux to permissive mode as a first resort. The security context usually just needs a minor adjustment. Run journalctl -xe first. Read the actual error before guessing.
When to use this versus alternatives
Use @development-tools when you need a complete C and C++ build environment for compiling software from source. Use @c-development when you only need the compiler, standard headers, and basic build utilities without the extra debugging and packaging tools. Use @rust-development when your project targets Rust and you need cargo, rustc, and the standard library. Use mock when you are building RPM packages and need a clean, reproducible environment that matches the official Fedora build infrastructure. Use dnf builddep when you want the package manager to automatically resolve and install every -devel dependency listed in an existing RPM spec file.