Cómo compilar y ejecutar C++ en macOS: guía práctica para Intel y Apple Silicon

Programar en C++ desde un Mac no exige instalar un entorno pesado ni tirar de GNU GCC. macOS trae de serie Apple Clang, el compilador incluido en las herramientas de desarrollo de Apple, junto con libc++ como biblioteca estándar de C++. Con las Command Line Tools instaladas basta para escribir, compilar, depurar y ejecutar programas C++ desde Terminal, tanto en Mac Intel como en equipos Apple Silicon (M1, M2, M3, M4 y generaciones posteriores).

Las claves para programar C++ en macOS en 20 segundos

  • Apple usa Clang como compilador C y C++, acompañado de libc++ como biblioteca estándar.
  • Las Command Line Tools se instalan sin descargar el entorno completo de Xcode.
  • clang++ programa.cpp -o programa basta para compilar un ejemplo sencillo.
  • Los Mac Apple Silicon generan código ARM64 nativo por defecto.
  • CMake, Homebrew, VS Code, Xcode y LLDB amplían el entorno para proyectos más grandes.

Para alguien acostumbrado a Linux la experiencia resulta bastante familiar, aunque el toolchain cambia: muchos desarrolladores esperan encontrar GNU GCC y se topan con un entorno que gira en torno a Clang, LLVM, los SDK de macOS y herramientas como xcrun. Conviene conocer algunos detalles desde el principio, sobre todo si el código viene de Linux, usa bibliotecas externas o tiene que compilar tanto en Intel x86-64 como en Apple Silicon ARM64.

Instalar el compilador C++ en macOS

La forma más rápida de empezar es instalar las Command Line Tools for Xcode desde Terminal:

xcode-select --install

macOS mostrará el diálogo correspondiente para descargar e instalar las herramientas. Apple ofrece este paquete precisamente para quien necesita trabajar desde Terminal o compilar proyectos UNIX y multiplataforma sin instalar la aplicación completa de Xcode. Incluye el SDK de macOS, páginas de manual y los binarios principales del toolchain.

Terminado el proceso, puedes comprobar dónde está el entorno activo:

xcode-select -p

Si solo están instaladas las Command Line Tools, la ubicación habitual es:

/Library/Developer/CommandLineTools

También puedes verificar la versión instalada:

pkgutil --pkg-info=com.apple.pkg.CLTools_Executables

Y comprobar el compilador:

clang++ --version

En un Mac Apple Silicon la salida debería indicar un objetivo similar a:

Target: arm64-apple-darwin...

Mientras que un Mac Intel usará normalmente:

Target: x86_64-apple-darwin...

Así compruebas rápidamente para qué arquitectura se está generando el código.

¿Clang o GCC en macOS?

Aquí aparece una confusión habitual. En muchos sistemas Linux, C++ se compila con:

g++

En macOS la herramienta estándar es:

clang++

Apple soporta oficialmente C++ mediante Apple Clang y libc++, ambos parte de su plataforma de desarrollo. Clang es el frontend del proyecto LLVM y soporta varias versiones del estándar C++, aunque el grado exacto de compatibilidad depende de la versión instalada: C++17 tiene soporte completo desde hace años, mientras que C++20, C++23 y lo previsto para C++26 hay que comprobarlo caso por caso, porque no todo llega necesariamente a la vez a cada versión de Clang o Apple Clang.

Por eso no conviene asumir que instalar la última versión de macOS da automáticamente soporte completo para todas las características del estándar más reciente.

Para ver el compilador disponible:

clang++ --version

Y localizarlo:

which clang++

También puedes usar xcrun, muy útil cuando conviven varios SDK o instalaciones de Xcode:

xcrun --find clang++

Para consultar el SDK activo:

xcrun --show-sdk-path

Esto ayuda a entender una diferencia importante respecto a muchos entornos Linux: en macOS, compilador, SDK y versión objetivo del sistema operativo van estrechamente ligados.

Crear, compilar y ejecutar el primer programa C++

Guarda el primer programa como hello.cpp:

#include <iostream>
#include <string>

int main()
{
    std::string name;
    int age;

    std::cout << "Enter your name: ";
    std::getline(std::cin, name);

    std::cout << "Enter your age: ";
    std::cin >> age;

    std::cout << "Hello " << name
              << ", you are " << age
              << " years old!n";

    return 0;
}

Se usa std::getline() para el nombre en lugar de std::cin >> name;, porque esa segunda opción se detiene en el primer espacio. Con std::getline() puedes meter nombres completos sin problema.

Para compilar:

clang++ hello.cpp -o hello

Si no aparecen errores, tendrás un ejecutable llamado hello. Puedes comprobarlo con ls -lh hello y ejecutarlo con:

./hello

El prefijo ./ es necesario porque, por motivos de seguridad y funcionamiento tradicional en sistemas Unix, el directorio actual no suele formar parte de la variable $PATH.

Si no indicas el nombre del ejecutable:

clang++ hello.cpp

el compilador genera por defecto a.out, que se ejecuta con ./a.out. Para mantener los proyectos organizados suele ser mejor usar siempre -o.

Elegir C++17, C++20 o C++23

Conviene declarar explícitamente el estándar que usa el proyecto. Por ejemplo, para C++17:

clang++ -std=c++17 hello.cpp -o hello

Para C++20:

clang++ -std=c++20 hello.cpp -o hello

Y para C++23:

clang++ -std=c++23 hello.cpp -o hello

Que exista la bandera no significa que absolutamente todas las características de ese estándar estén implementadas. LLVM mantiene una tabla detallada con el estado de compatibilidad de Clang, y Apple publica además información específica sobre qué soportan sus plataformas (más detalle en nuestro repaso de C++23 en la práctica con GCC y Clang).

Para un proyecto nuevo sin necesidad de características muy recientes, C++20 suele ser una elección razonable:

clang++ -std=c++20 hello.cpp -o hello

Compilar mejor: warnings, optimización y depuración

Para aprender C++ o trabajar en un proyecto real no conviene quedarse en clang++ hello.cpp a secas. Los warnings del compilador detectan errores antes de ejecutar el programa. Una configuración razonable para desarrollo sería:

clang++ -std=c++20 -Wall -Wextra -Wpedantic hello.cpp -o hello

Estas opciones activan distintos grupos de advertencias. También puedes añadir -Werror para convertir los warnings en errores:

clang++ -std=c++20 -Wall -Wextra -Wpedantic -Werror hello.cpp -o hello

Es una política útil en algunos proyectos y en integración continua, aunque durante el desarrollo puede resultar demasiado estricta según el código y las bibliotecas que uses.

Compilar para depuración

Para generar información útil para un debugger:

clang++ -std=c++20 -Wall -Wextra -g hello.cpp -o hello

La opción -g incluye información de depuración. macOS trae LLDB, el debugger de LLVM. Se inicia con:

lldb ./hello

Dentro de LLDB, run ejecuta el programa. También puedes colocar breakpoints:

breakpoint set --name main

o su forma abreviada:

b main

Después, run detendrá el programa al llegar a main().

Compilar una versión optimizada

Clang tiene distintos niveles de optimización:

-O0
-O1
-O2
-O3
-Os

Para desarrollo suele usarse -O0 o una optimización moderada. Para una versión optimizada:

clang++ -std=c++20 -O2 hello.cpp -o hello

-O3 aplica optimizaciones más agresivas:

clang++ -std=c++20 -O3 hello.cpp -o hello

Más optimización no implica automáticamente que cualquier programa vaya a ir más rápido. La decisión depende del proyecto y, cuando el rendimiento importa de verdad, debería apoyarse en benchmarks.

Una configuración práctica durante el desarrollo

Un comando razonable para el día a día:

clang++ -std=c++20 -Wall -Wextra -Wpedantic -g hello.cpp -o hello

Y para una compilación optimizada:

clang++ -std=c++20 -Wall -Wextra -Wpedantic -O2 hello.cpp -o hello

Apple Silicon cambia algunas cosas que conviene conocer

Los Mac modernos usan procesadores Apple Silicon basados en ARM64. Para comprobar la arquitectura:

uname -m

En Apple Silicon verás arm64; en un Mac Intel, x86_64. También puedes analizar un ejecutable recién compilado:

file ./hello

En Apple Silicon debería aparecer algo como Mach-O 64-bit executable arm64; en Intel, Mach-O 64-bit executable x86_64.

Esto importa especialmente cuando entran en juego bibliotecas externas: un programa ARM64 no puede enlazar directamente con una biblioteca que solo existe para x86-64. Ese es uno de los motivos por los que algunos proyectos antiguos dan errores de compilación o de linking al migrarlos de un Mac Intel a Apple Silicon.

Compilar explícitamente para ARM64

Puedes indicar la arquitectura:

clang++ -arch arm64 hello.cpp -o hello

Para Intel:

clang++ -arch x86_64 hello.cpp -o hello

La segunda opción solo funcionará bien cuando las bibliotecas y el SDK necesarios estén disponibles para esa arquitectura.

macOS también permite crear Universal Binaries con código para más de una arquitectura. Puedes compilar ambas versiones por separado:

clang++ -arch arm64 hello.cpp -o hello-arm64
clang++ -arch x86_64 hello.cpp -o hello-x86_64

Y combinarlas con:

lipo -create hello-arm64 hello-x86_64 -output hello-universal

Después, file hello-universal te dirá qué arquitecturas incluye.

Para un programa personal que solo va a correr en un Mac Apple Silicon, normalmente no hace falta nada de esto: Clang selecciona la arquitectura nativa automáticamente.

Por qué bits/stdc++.h falla en macOS

Una de las sorpresas más habituales al copiar ejemplos de C++ de internet es encontrarse con:

#include <bits/stdc++.h>

y recibir un error parecido a:

fatal error: 'bits/stdc++.h' file not found

El problema no es C++ ni macOS. bits/stdc++.h no forma parte del estándar C++. Es una cabecera propia de implementaciones de GNU libstdc++, muy usada en programación competitiva porque mete de golpe un montón de cabeceras. Apple usa Clang con libc++, así que no conviene depender de ella.

Lo correcto es incluir exactamente lo que necesita el programa:

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

Además de arreglar el error, esto tiene una ventaja de portabilidad: el código deja de depender de una particularidad de una implementación concreta. Un programa que use std::vector, std::sort, std::string y std::cout debería declarar esas mismas cuatro cabeceras. La regla práctica es sencilla: si quieres C++ portable entre macOS, Linux y Windows, usa cabeceras estándar.

Instalar bibliotecas C++ externas en macOS

Los programas reales suelen necesitar algo más que la biblioteca estándar. Aquí entra Homebrew, la opción habitual para instalar dependencias. Por ejemplo, para Boost:

brew install boost

Para OpenSSL:

brew install openssl

Para CMake:

brew install cmake

Instalar una biblioteca no significa que Clang vaya a encontrarla automáticamente. Puede hacer falta indicar rutas de cabeceras y bibliotecas:

clang++ main.cpp 
  -I/ruta/include 
  -L/ruta/lib 
  -lmi_biblioteca 
  -o programa

Las opciones principales:

Opción

Función

-I

Añade una ruta de cabeceras

-L

Añade una ruta de bibliotecas

-l

Indica una biblioteca que hay que enlazar

-std=

Selecciona el estándar C++

-o

Define el nombre del ejecutable

-g

Añade información de depuración

-O2

Activa optimizaciones

-Wall

Activa warnings habituales

En proyectos grandes, escribir a mano todos estos parámetros deja de ser práctico. Ahí es donde entra CMake.

Pasar de un archivo a un proyecto con CMake

Para un único hello.cpp, Clang es suficiente. Cuando aparecen diez, cien o miles de archivos, bibliotecas y configuraciones distintas, interesa un sistema de build. CMake es una de las opciones más extendidas en proyectos C++ multiplataforma.

Una estructura sencilla:

myproject/
??? CMakeLists.txt
??? src/
    ??? main.cpp

El CMakeLists.txt:

cmake_minimum_required(VERSION 3.20)

project(MyProject LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(myapp src/main.cpp)

Después:

mkdir build
cd build
cmake ..
cmake --build .

O con el enfoque moderno:

cmake -S . -B build
cmake --build build

El ejecutable aparece dentro del directorio de compilación. Este modelo tiene una ventaja clara si trabajas a la vez en macOS y Linux: el proyecto deja de depender de una colección de comandos manuales específicos de cada máquina.

Clang, Xcode, VS Code o solo Terminal

No hace falta instalar Xcode completo para programar C++.

Entorno

Cuándo puede interesar

Terminal + Clang

Aprendizaje, scripts, proyectos pequeños

VS Code + Clang

Desarrollo general y multiplataforma

Xcode

Software integrado con plataformas Apple

CLion

Proyectos C++ grandes y CMake

Vim/Neovim + Clang

Entornos centrados en Terminal

Las Command Line Tools bastan para numerosos proyectos C++. Xcode completo empieza a hacer falta cuando se necesitan determinadas herramientas que Apple distribuye solo con el IDE: xcodebuild y otras utilidades específicas no forman parte del paquete independiente de Command Line Tools.

Qué lenguaje usar en macOS además de C++

C++ no es la única opción razonable en el ecosistema de Apple, y muchas veces conviene combinarlo con otro lenguaje según la parte del proyecto. Esta tabla resume cuándo tiene sentido cada uno y cómo se lleva con C++ en el mismo proyecto:

Lenguaje

Cuándo tiene sentido en macOS

Interoperabilidad con C++

C++ (Clang/libc++)

Rendimiento máximo, control fino de memoria, código multiplataforma

Nativa

Swift

Apps de escritorio o iOS con interfaz nativa (SwiftUI/AppKit)

Interop directa desde Swift 5.9, sin capa C intermedia

Objective-C

Mantenimiento de código legacy sobre Cocoa/AppKit

Objective-C++ (.mm) mezcla ambos lenguajes en el mismo archivo

Rust

Seguridad de memoria con rendimiento cercano a C++

Vía FFI o crates como cxx, sin ABI estable compartido

Python

Scripting, prototipado, pegamento entre herramientas

ctypes o pybind11 para llamar a código C++

En la práctica, la mayoría de proyectos macOS serios no se quedan en un solo lenguaje. Es habitual escribir el núcleo de cálculo o el motor en C++ y dejar la interfaz en Swift, aprovechando que Swift puede importar C++ directamente desde 2023 sin pasar por una capa intermedia en C. Para piezas antiguas del sistema o frameworks de Apple heredados, Objective-C++ sigue siendo el pegamento habitual entre el mundo C++ y Cocoa. Y si el objetivo es una CLI o una utilidad de sistema donde interesa más la seguridad de memoria que la interoperabilidad fina, Rust es una alternativa cada vez más común, aunque su integración con C++ pasa siempre por una capa FFI explícita, no por comunicación nativa.

Para elegir compilador C, y no solo C++, en macOS y en general, puede interesar también nuestra comparativa de GCC, Clang y TCC en 2026.

Errores habituales al compilar C++ en macOS

clang++: command not found

Comprueba primero xcode-select -p. Si las herramientas no están instaladas:

xcode-select --install

'bits/stdc++.h' file not found

Sustituye esa cabecera no estándar por las cabeceras C++ que use de verdad el programa.

Undefined symbols for architecture arm64

Suele indicar un problema en el enlazado: una biblioteca que no se enlaza correctamente o una dependencia compilada para otra arquitectura. Puedes comprobarla con:

file /ruta/a/libbiblioteca.dylib

o:

lipo -info /ruta/a/libbiblioteca.dylib

El programa compila en Linux pero no en macOS

No todo lo disponible en Linux es C++ estándar. El programa puede depender de cabeceras específicas de GNU, APIs propias de Linux, llamadas al sistema, bibliotecas no instaladas, rutas de filesystem concretas o extensiones particulares de GCC. En ese caso el problema no es necesariamente Clang, puede ser simplemente que el código no sea portable.

library not found

Comprueba dónde está instalada la biblioteca y pasa la ruta con -L, además de enlazarla con -l.

header file not found

Suele resolverse indicando su ubicación:

clang++ main.cpp -I/ruta/include -o programa

Un pequeño entorno C++ completo en menos de cinco minutos

Para quien acaba de recibir un Mac y solo quiere empezar:

xcode-select --install

Comprobar:

clang++ --version

Crear:

nano hello.cpp

E introducir:

#include <iostream>

int main()
{
    std::cout << "Hello from C++ on macOS!n";
    return 0;
}

Compilar:

clang++ -std=c++20 -Wall -Wextra -Wpedantic hello.cpp -o hello

Ejecutar:

./hello

Comprobar qué se ha generado:

file ./hello

Y si hay que depurarlo:

clang++ -std=c++20 -g hello.cpp -o hello
lldb ./hello

Con estos pasos ya tienes un entorno C++ completamente funcional sin abrir ningún IDE. Para proyectos más grandes, el siguiente paso razonable es incorporar CMake, Git, un editor con soporte para clangd y un gestor de dependencias adecuado al proyecto.

macOS no intenta reproducir exactamente el entorno GNU habitual de muchas distribuciones Linux. Su toolchain gira en torno a Apple Clang, LLVM, libc++, LLDB y los SDK de Apple. Entender esa diferencia evita buena parte de los problemas que aparecen al mover código C++ entre ambos sistemas.

Preguntas frecuentes

¿Qué compilador C++ usa macOS?

Apple usa Apple Clang como compilador C++ oficial de sus herramientas de desarrollo, con libc++ como implementación de la biblioteca estándar. Ambos están disponibles mediante Xcode y las Command Line Tools.

¿Hace falta instalar Xcode completo para programar C++ en Mac?

No. Para compilar programas C++ desde Terminal suele bastar con instalar las Command Line Tools con xcode-select --install. Xcode completo resulta útil o necesario para determinadas herramientas y proyectos específicos de las plataformas Apple.

¿Cómo se compila un archivo C++ en macOS?

Un ejemplo sencillo se compila con clang++ hello.cpp -o hello y se ejecuta después con ./hello. Puedes añadir -std=c++20 o el estándar que necesite el proyecto.

¿Por qué bits/stdc++.h no funciona en macOS?

Porque no es una cabecera estándar de C++. Está asociada sobre todo al entorno GNU libstdc++ y no forma parte de libc++, la biblioteca que usa Apple. Para escribir código portable hay que incluir las cabeceras estándar necesarias una a una.

Fuentes: Apple Developer Documentation («Installing the Command Line Tools for Xcode», «C++ Language Support» y «Command-line tools»), LLVM Project («C++ Support in Clang») y appleismo.com como fuente adicional.

Imagen: appleismo.com

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP