Skip to main content

Modularizando tu proyecto C++ con Meson

⏱ Dedicación recomendada: 0 minutos
Esto considera el contenido visible y relevante, e ignora texto colapsado o marcado como opcional.


r8vnhill/echo-app-cpp-meson
Glosario rápido
TODO
  • Añadir un glosario rápido.

🏗️ Estructura esperada del proyecto

TODO
  • Añadir un diagrama de flujo de la estructura del proyecto.

📦 Paso 1: Crear la estructura de carpetas

Desde la raíz del proyecto:

src/scripts/ps1/CreateProjectStructure.ps1
@{
App = @("src/app/main.cpp", "src/app/meson.build")
Core = @("src/core/echo.cpp", "src/core/echo.hpp", "src/core/meson.build")
}.GetEnumerator() | ForEach-Object {
$module = $_.Key
$files = $_.Value

Write-Host "📁 Creating structure for module: $module" -ForegroundColor Cyan

foreach ($file in $files) {
$dir = Split-Path $file -Parent
if (-not (Test-Path $dir)) {
New-Item -Path $dir -ItemType Directory -Force | Out-Null
}
New-Item -Path $file -ItemType File -Force | Out-Null
Write-Host "✅ $file" -ForegroundColor Green
}
}

Write-Host "🟢 Project initialized successfully." -ForegroundColor Green
¿Qué acabamos de hacer?

Este script de PowerShell automatiza la creación de una estructura de carpetas y archivos mínima para un proyecto modular en C++ usando Meson como sistema de construcción.

  • Define un diccionario con dos módulos: App y Core, cada uno asociado a los archivos que necesita.
  • Por cada archivo:
    • Crea la carpeta contenedora si no existe (por ejemplo, src/app/ o src/core/).
    • Crea un archivo vacío (main.cpp, echo.cpp, meson.build, etc.) en la ubicación indicada.
    • Muestra en consola un mensaje de confirmación () por cada archivo creado.

Puedes crear el archivo CreateProjectStructure.ps1 y ejecutarlo desde PowerShell para crear la estructura de carpetas y archivos automáticamente.

.\scripts\ps1\CreateProjectStructure.ps1
Limpieza

Puedes borrar los archivos creados en la lección pasada o guardarlos como recuerdo.

src/scripts/ps1/CleanupProject.ps1
'src\main.cpp', 'src\meson.build' | Remove-Item -Force -Verbose

🧾 Paso 2: Declarar el archivo raíz meson.build

En este archivo indicamos a Meson que estamos creando un proyecto en C++, especificamos su versión, y declaramos qué subdirectorios contienen código que debe ser compilado.

meson.build
project('echo-app', 'cpp', version: '0.2.0')  # Nombre, lenguaje y versión del proyecto

subdir('src/core') # Biblioteca reutilizable
subdir('src/app') # Ejecutable principal
¿Qué acabamos de hacer?

Este archivo es el punto de entrada del sistema de construcción de Meson. Declara el proyecto y registra los subdirectorios que contienen sus propios archivos meson.build. Así, Meson podrá compilar correctamente tanto la biblioteca (core) como la aplicación (app).

🧩 Paso 3: Implementar la biblioteca core

En este paso definimos la biblioteca core, que encapsula una función simple echo. Para ello, configuramos el archivo meson.build del módulo y escribimos su implementación.

src/core/meson.build
core_sources = files('echo.cpp')

core_lib = static_library(
'core',
core_sources,
include_directories: include_directories('.'),
cpp_args: ['-std=c++23'],
)
¿Qué acabamos de hacer?

Este archivo configura la compilación del módulo core como una biblioteca estática.

  • static_library('core', ...) indica que se generará una .a o .lib con ese nombre.
  • Se incluyen los archivos fuente del módulo (echo.cpp) y el directorio actual como ruta de inclusión (.), donde está el archivo echo.hpp.
  • Se fuerza el estándar c++23 para habilitar características modernas del lenguaje.

Esto permite que otros módulos, como app, puedan vincularse contra core y reutilizar sus funciones.

✍️ Implementación de echo

Ahora escribimos la función echo, que devuelve una copia del mensaje recibido. Usamos std::string_view para mayor eficiencia en el paso de argumentos.

src/core/echo.hpp
#pragma once

#include <string>
#include <string_view>

[[nodiscard]] std::string echo(std::string_view message);
src/core/echo.cpp
#include "echo.hpp"

std::string echo(std::string_view message) {
return {message.begin(), message.end()};
}
¿Qué acabamos de hacer?
  • En echo.hpp, definimos la interfaz pública de la biblioteca.
    Usamos std::string_view como entrada para aceptar cadenas sin copiar, y [[nodiscard]] para evitar que se ignore el resultado de la función.

  • En echo.cpp, implementamos echo devolviendo una copia explícita del contenido usando rangos. Esto funciona igual que std::string(message) pero es más explícito en su conversión.

Esta biblioteca es mínima pero funcional. Ilustra cómo separar la lógica de negocio (core) del ejecutable principal (app), siguiendo una estructura modular mantenible.

🚀 Módulo app: ejecutable

src/app/meson.build
app_sources = files('main.cpp')
executable('app', app_sources,
dependencies: [],
link_with: core_lib,
include_directories: include_directories('..')
)

Código principal:

src/app/main.cpp
#include <iostream>
#include "core/echo.hpp"

int main() {
std::cout << echo("Hello from Meson!") << std::endl;
return 0;
}

🔨 Compilación

Desde la raíz del proyecto:

meson setup build
meson compile -C build

Y ejecuta el binario:

./build/src/app/app
Echo: Hello from Meson!
¿Qué acabamos de hacer?

El ejecutable app se compila en build/src/app/app y enlaza con la biblioteca core. Gracias a la configuración modular, puedes mantener core como una unidad reutilizable o independiente.