当前位置: 首页 > article >正文

C++ 编译 g++ -> make -> cmake

目录

  • 1.Windows上安装MinGW
  • 2.构建一个 C++ 项目
  • 3.g++ 编译
  • 4.make 编译
  • 5.cmake 编译

在这里插入图片描述

1.Windows上安装MinGW

https://www.mingw-w64.org/

预构建工具链,WinLibs
在这里插入图片描述
https://winlibs.com,此处使用 GCC 14.2.0 (with POSIX threads) + MinGW-w64 12.0.0 UCRT + Win64 + without LLVM/Clang/LLD/LLDB 19.1.1,zip 文件链接:https://github.com/brechtsanders/winlibs_mingw/releases/download/14.2.0posix-19.1.1-12.0.0-ucrt-r2/winlibs-x86_64-posix-seh-gcc-14.2.0-mingw-w64ucrt-12.0.0-r2.zip

在这里插入图片描述

各项参数

  1. 架构
    Win32 - i686 - Windows 32-bit version, runs natively on and compiles for Windows 32-bit (also runs on Windows 64-bit, but in 32-bit mode)
    Win64 - x86_64 - Windows 64-bit version, runs natively on and compiles for Windows 64-bit (will not run on Windows 32-bit)

  2. 线程库
    GCC for Windows can be built with the follwing threading libraries:
    POSIX (best compatibility with other platforms)
    WIN32 (native Windows thread but misses POSIX threads / pthread.h)
    MCF (since GCC 13, see also: MCF Gthread Library)
    For portability reasons (compatibility with other platforms) the builds published here use the POSIX threading library.
    Since GCC 13 some builds with the MCF threading model were also released.

  3. 异常处理模型
    SEH (Structured Exception Handling):
    64 位系统的默认异常处理模型。
    推荐用于 64 位开发。
    DWARF:
    适用于 32 位系统的异常处理模型。
    性能较好,但仅限于 32 位开发。
    SJLJ (Set Jump/Long Jump):
    老旧的异常处理模型,性能稍差。
    不推荐使用,除非有兼容性需求。

  4. 运行时库
    UCRT (Universal C Runtime):
    现代 Windows 的通用运行时库,推荐。
    MSVCRT (Microsoft C Runtime Library):
    使用微软的运行时库,适合需要兼容 Visual Studio 的场景。

另外,WinLibs 在 https://sourceforge.net/projects/winlibs-mingw/files 也有托管,https://sourceforge.net/projects/winlibs-mingw/files/14.2.0posix-19.1.1-12.0.0-ucrt-r2/winlibs-x86_64-posix-seh-gcc-14.2.0-mingw-w64ucrt-12.0.0-r2.zip/download

解压即可,随后将 bin 目录配置到 PATH 即可全局使用命令。

g++ -v
g++ --help

2.构建一个 C++ 项目

项目名称为:student_management

student_management
├── main.cpp
├── include
│   ├── manager.h
│   └── student.h
└── src
    ├── manager.cpp
    └── student.cpp

main.cpp

#include <iostream>
#include "include/manager.h"

int main() {
    using namespace StudentManagement;

    Manager manager;

    manager.addStudent(Student(1, "Alice", 20));
    manager.addStudent(Student(2, "Bob", 22));
    manager.addStudent(Student(3, "Charlie", 21));

    std::cout << "All Students:" << std::endl;
    manager.displayAllStudents();

    std::cout << "\nFinding Student with ID 2:" << std::endl;
    Student *student = manager.findStudent(2);
    if (student) {
        student->display();
    } else {
        std::cout << "Student not found." << std::endl;
    }

    std::cout << "\nRemoving Student with ID 2:" << std::endl;
    manager.removeStudent(2);
    manager.displayAllStudents();

    std::cout << "按任意键退出程序..." << std::endl;
    std::cin.get(); // 等待用户按下回车键

    return 0;
}

include/manager.h

#ifndef CPP_COMPILE_DEMO_MANAGER_H
#define CPP_COMPILE_DEMO_MANAGER_H

#include <vector>
#include <string>
#include "student.h"

namespace StudentManagement {
    class Manager {
    public:
        void addStudent(const Student &student);

        void removeStudent(int id);

        void displayAllStudents() const;

        Student *findStudent(int id) const;

    private:
        std::vector<Student> students;
    };
}

#endif // CPP_COMPILE_DEMO_MANAGER_H

include/student.h

#ifndef CPP_COMPILE_DEMO_STUDENT_H
#define CPP_COMPILE_DEMO_STUDENT_H

#include <string>

namespace StudentManagement {
    class Student {
    public:
        Student(int id, const std::string &name, int age);

        int getId() const;

        std::string getName() const;

        int getAge() const;

        void display() const;

    private:
        int id;
        std::string name;
        int age;
    };
}
#endif //CPP_COMPILE_DEMO_STUDENT_H

src/manager.cpp

#include "../include/manager.h"

namespace StudentManagement {
    void Manager::addStudent(const Student &student) {
        students.push_back(student);
    }

    void Manager::removeStudent(int id) {
        for (auto it = students.begin(); it != students.end(); ++it) {
            if (it->getId() == id) {
                students.erase(it);
                return;
            }
        }
    }

    void Manager::displayAllStudents() const {
        for (const auto &student: students) {
            student.display();
        }
    }

    Student *Manager::findStudent(int id) const {
        for (const auto &student: students) {
            if (student.getId() == id) {
                return const_cast<Student *>(&student);
            }
        }
        return nullptr;
    }
}

src/student.cpp

#include <iostream>
#include "../include/student.h"

namespace StudentManagement {
    Student::Student(int id, const std::string &name, int age)
            : id(id), name(name), age(age) {}

    int Student::getId() const {
        return id;
    }

    std::string Student::getName() const {
        return name;
    }

    int Student::getAge() const {
        return age;
    }

    void Student::display() const {
        std::cout << "ID: " << id << ", Name: " << name << ", Age: " << age << std::endl;
    }
}

3.g++ 编译

# 预处理
g++ -E src/manager.cpp -o src/manager.i
g++ -E src/student.cpp -o src/student.i
g++ -E main.cpp -o main.i

# 编译
g++ -S src/manager.i -o src/manager.s
g++ -S src/student.i -o src/student.s
g++ -S main.i -o main.s

# 汇编
g++ -c src/manager.s -o src/manager.o
g++ -c src/student.s -o src/student.o
g++ -c main.s -o main.o

# 链接
g++ main.o src/student.o src/manager.o -o student_management

# 清理
del *.i *.s *.o src\*.i src\*.s src\*.o
g++ main.cpp src/manager.cpp src/student.cpp -o student_management

4.make 编译

Makefile

# 定义编译器
CXX = g++  # 指定使用的 C++ 编译器,默认是 g++

# 定义编译器选项
CXXFLAGS = -Wall -std=c++17  # 编译器选项
# -Wall: 开启所有警告信息
# -std=c++17: 使用 C++17 标准

# 定义目标文件名
TARGET = student_management  # 最终生成的可执行文件名

# 定义源文件列表
SOURCES = main.cpp src/manager.cpp src/student.cpp  # 所有源文件列表

# 自动生成目标文件列表(将源文件名中的 .cpp 替换为 .o)
OBJECTS = $(SOURCES:.cpp=.o)  # 自动生成目标文件列表

# 默认目标(make 命令执行时的默认目标)
all: $(TARGET)  # 默认目标是构建 $(TARGET)

# 构建最终目标文件
$(TARGET): $(OBJECTS)  # 依赖于所有目标文件
	$(CXX) $(OBJECTS) -o $@
# 使用 g++ 将所有目标文件链接成最终的可执行文件
# $@ 表示目标文件名(这里是 $(TARGET))
# $(OBJECTS) 是所有目标文件的列表

# 生成目标文件的规则
%.o: %.cpp  # 每个目标文件(.o)依赖于对应的源文件(.cpp)
	$(CXX) $(CXXFLAGS) -c $< -o $@
# 编译单个源文件生成目标文件
# $< 表示依赖列表中的第一个依赖项(这里是 .cpp 文件)
# $@ 表示目标文件名(这里是 .o 文件)
# -c 表示只编译,不链接
# -o 指定输出文件名

# 清理生成的文件
clean:  # 定义一个名为 "clean" 的目标,用于清理编译生成的文件
	del *.o src\*.o >nul 2>nul
# rm -f $(TARGET) $(OBJECTS) *.i *.s src/*.i src/*.s
# 删除所有生成的文件
# rm -f: 强制删除文件,不提示
# $(TARGET): 删除最终的可执行文件
# $(OBJECTS): 删除所有目标文件
# *.i, *.s, src/*.i, src/*.s: 删除预处理和汇编生成的中间文件
# >nul:将标准输出(如果有)重定向到nul,丢弃输出。
# 2>nul:将错误输出(如文件不存在的提示)重定向到nul,丢弃错误信息。

将 Makefile 文件放至项目根目录下,随后编译:

mingw32-make
# 等价于:
# g++   -Wall -std=c++17   -c main.cpp -o main.o
# g++   -Wall -std=c++17   -c src/manager.cpp -o src/manager.o
# g++   -Wall -std=c++17   -c src/student.cpp -o src/student.o
# g++   main.o src/manager.o src/student.o   -o student_management.exe

清理中间文件及编译结果:

mingw32-make clean

5.cmake 编译

CMakeLists.txt

# 设置CMake的最低版本要求
cmake_minimum_required(VERSION 3.23)  # 指定最低版本为3.23,确保CMake的兼容性

# 设置项目名称
project(student_management)  # 定义项目名称为student_management,CMake会根据这个名称生成目标

# 设置C++标准
set(CMAKE_CXX_STANDARD 17)  # 指定使用C++17标准,确保编译器支持C++17特性

# 设置编译器选项
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")  # 添加编译器警告选项-Wall,开启所有警告信息

# 定义源文件
set(SOURCES main.cpp src/manager.cpp src/student.cpp)  # 定义源文件列表,指定需要编译的源文件

# 添加可执行文件
add_executable(student_management ${SOURCES})  # 根据源文件生成可执行文件,目标名称为cpp_compile_demo


## 定义清理目标
#add_custom_target(
#        clean ALL  # 定义一个自定义目标clean,用于清理生成的文件
#        COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/src/*.o"  # 删除src目录下的所有文件
#        COMMAND ${CMAKE_COMMAND} -E remove "${CMAKE_BINARY_DIR}/*.o"  # 删除所有目标文件(.o文件)
#        COMMAND ${CMAKE_COMMAND} -E remove "${CMAKE_BINARY_DIR}/${PROJECT_NAME}"  # 删除项目生成的可执行文件
#        COMMENT "Cleaning up build artifacts..."  # 清理时的提示信息
#)  # 自定义清理目标

将 CMakeLists.txt 文件放至项目根目录下,选择合适的生成器生成makefile等文件:

# Unix Makefiles
cmake -G "Unix Makefiles" .
# MinGW Makefiles,mingw32-make 专用,上文已有,不再演示
cmake -G "MinGW Makefiles" .
# Ninja,生成 build.ninja 文件
cmake -G "Ninja" .

此处采用 Ninja,Ninja 与 make 属于同类工具,但 Ninja 比 make 更快

编译

ninja

清理

ninja clean

http://www.kler.cn/a/537005.html

相关文章:

  • 力扣刷题思路
  • ubuntu20使用tigervnc远程桌面配置记录
  • Spring Boot 自动装配原理与优化实践
  • 【BUUCTF逆向题】[MRCTF2020]Transform
  • 【玩转全栈】--创建一个自己的vue项目
  • vscode 如何通过Continue引入AI 助手deepseek
  • idea 找不到或者无法加载主类
  • 线性代数于工程应用中的实践:以代码实例拆解图像平滑问题的求解逻辑
  • Retrieval-Augmented Generation,检索增强生成流程
  • HTML01-知云接力
  • 【C语言】C语言经典面试题详解
  • 传华为2025年新品更新 用上超声波指纹nova上红枫
  • 大模型做导师之方案版本比较
  • Unity Shader Graph 2D - 使用DeepSeek协助绘制一个爱心
  • Spring Boot启动内嵌tocmat原理
  • mysql的原理及经验
  • Vue3+codemirror6实现公式(规则)编辑器
  • 记录一次mysql主从
  • 【远程控制】安装虚拟显示器
  • 快速上手——.net封装使用DeekSeek-V3 模型
  • openCV函数使用(一)
  • JMeter通过BeanShell写入CSV文件中的中文乱码
  • MoviePy,利用Python自动剪辑tiktok视频
  • 【Unity 墓地和自然环境场景资产包】PBR Graveyard and Nature Set 2.0 高质量的墓地3D 模型,丰富的自然环境元素,轻松构建具有沉浸感和氛围感的游戏世界
  • 三级等保、二级等保谁更高级 ?等保都有哪些?
  • Gateway路由匹配规则详解