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

面试后查缺补漏--cmake,makefiles,g++,gcc(自写精华版)

概览

在Linux C++开发中,编译构建涉及以下核心工具:

源代码(.cpp/.h) → 编译器(g++/gcc) → 目标文件(.o) → 链接器(ld) → 可执行文件↓
构建系统(Makefile/CMake) 负责管理整个流程

1.g++,gcc

  • gcc: GNU C 编译器,主要用于编译 C 程序

  • g++: GNU C++ 编译器,主要用于编译 C++ 程序

  1. 单文件g++ -o 输出文件名 源文件.cpp

  2. 多文件: 列出所有源文件或分别编译后链接

  3. 常用选项-Wall(警告), -g(调试), -O(优化)

  4. 运行./可执行文件名

2.makefiles- 构建自动化

Makefile 是一个文本文件,包含了一系列规则,告诉 make 工具如何编译和链接程序。

基本语法结构

makefile

目标: 依赖命令

注意: 命令前必须是 Tab 字符,不能是空格!

简单的 Makefile 示例

示例 1: 基础单文件编译

makefile

# 注释以 # 开头
hello: hello.cppg++ -o hello hello.cppclean:rm -f hello

使用:

bash

make        # 编译程序
make clean  # 清理生成的文件

示例 2: 多文件项目

假设项目结构:

text

project/
├── main.cpp
├── utils.cpp
├── utils.h
└── Makefile

对应的 Makefile:

makefile

# 定义变量
CXX = g++
CXXFLAGS = -Wall -std=c++11
TARGET = myapp
OBJS = main.o utils.o# 默认目标
$(TARGET): $(OBJS)$(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS)main.o: main.cpp utils.h$(CXX) $(CXXFLAGS) -c main.cpputils.o: utils.cpp utils.h$(CXX) $(CXXFLAGS) -c utils.cppclean:rm -f $(TARGET) $(OBJS).PHONY: clean  # 声明 clean 为伪目标

完整的 Makefile 模板

makefile

# 编译器设置
CXX = g++
CXXFLAGS = -Wall -g -std=c++14
LDFLAGS = # 项目设置
TARGET = myprogram
SRCDIR = src
OBJDIR = obj# 自动查找源文件
SOURCES = $(wildcard $(SRCDIR)/*.cpp)
OBJECTS = $(SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)# 默认目标
$(TARGET): $(OBJECTS)$(CXX) $(OBJECTS) -o $(TARGET) $(LDFLAGS)# 编译源文件为目标文件
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $(OBJDIR)$(CXX) $(CXXFLAGS) -c $< -o $@# 创建目标目录
$(OBJDIR):mkdir -p $(OBJDIR)# 清理
clean:rm -rf $(OBJDIR) $(TARGET)# 安装
install: $(TARGET)cp $(TARGET) /usr/local/bin/# 声明伪目标
.PHONY: clean install

常用变量和自动变量

  • $@: 当前目标名称

  • $<: 第一个依赖项

  • $^: 所有依赖项

  • $?: 比目标更新的依赖项

  • $*: 不包含扩展名的目标文件

实际开发步骤

1. 创建项目结构

text

myproject/
├── src/
│   ├── main.cpp
│   ├── utils.cpp
│   └── utils.h
├── obj/           # 自动创建
└── Makefile

2. 编写 Makefile

使用上面的模板,根据项目需求调整。

3. 构建项目

bash

make              # 编译项目
./myprogram       # 运行程序
make clean        # 清理构建文件

4. 重新构建

bash

make              # make 会自动检测哪些文件需要重新编译

高级特性

条件判断

makefile

DEBUG = 1
ifeq ($(DEBUG), 1)CXXFLAGS += -DDEBUG -O0
elseCXXFLAGS += -O2
endif

包含其他 Makefile

makefile

include config.mk

函数使用

makefile

SOURCES = $(wildcard src/*.cpp)
OBJECTS = $(patsubst src/%.cpp,obj/%.o,$(SOURCES))

实用技巧

  1. 使用 -j 选项并行编译

    bash

    make -j4  # 使用4个线程并行编译
  2. 查看详细输出

    bash

    make V=1  # 显示完整的编译命令
  3. 只编译不链接

    bash

    make main.o  # 只编译 main.cpp

总结

Makefile 的核心优势:

  • 自动化: 自动检测文件变化,只重新编译必要的文件

  • 高效: 支持并行编译,加快构建速度

  • 灵活: 可以定义复杂的构建规则

  • 可移植: 在不同 Unix-like 系统上都能工作

对于小型到中型 C++ 项目,Makefile 是一个非常实用的构建工具!

3.cmake- 跨平台构建系统

CMake 是一个跨平台的自动化构建系统,可以生成 Makefile、Visual Studio 项目文件等。它比直接写 Makefile 更高级和方便。

CMake 使用 CMakeLists.txt 文件来描述构建过程,然后生成对应平台的构建文件。

基本操作步骤

1. 创建项目结构

text

myproject/
├── CMakeLists.txt
├── src/
│   ├── main.cpp
│   ├── utils.cpp
│   └── utils.h
└── build/          # 建议的构建目录

2. 编写 CMakeLists.txt

最简单的 CMakeLists.txt

cmake

# 指定 CMake 最低版本要求
cmake_minimum_required(VERSION 3.10)# 设置项目名称
project(MyProject)# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)# 添加可执行文件
add_executable(myapp src/main.cpp src/utils.cpp)

3. 构建项目

bash

# 进入构建目录
mkdir build
cd build# 生成构建系统
cmake ..# 编译项目
make# 运行程序
./myapp

完整的 CMakeLists.txt 示例

cmake

# CMake 最低版本要求
cmake_minimum_required(VERSION 3.10)# 项目定义
project(MyProject VERSION 1.0DESCRIPTION "A simple C++ project"LANGUAGES CXX
)# 设置 C++ 标准和相关属性
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)# 编译选项
if(CMAKE_BUILD_TYPE STREQUAL "Debug")set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -g -O0")
else()set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O2")
endif()# 包含目录
include_directories(${CMAKE_SOURCE_DIR}/src)# 查找源文件
file(GLOB SOURCES "src/*.cpp")# 创建可执行文件
add_executable(${PROJECT_NAME} ${SOURCES})# 链接库(如果有)
# target_link_libraries(${PROJECT_NAME} pthread)# 安装规则(可选)
install(TARGETS ${PROJECT_NAME} DESTINATION bin)

更高级的项目结构

对于多目录项目:

text

myproject/
├── CMakeLists.txt
├── src/
│   ├── CMakeLists.txt
│   ├── main.cpp
│   └── utils.cpp
├── include/
│   └── utils.h
└── build/

根目录 CMakeLists.txt

cmake

cmake_minimum_required(VERSION 3.10)
project(MyProject)# 添加子目录
add_subdirectory(src)

src/CMakeLists.txt

cmake

# 包含头文件目录
include_directories(${CMAKE_SOURCE_DIR}/include)# 源文件
set(SOURCES main.cpp utils.cpp)# 创建可执行文件
add_executable(${PROJECT_NAME} ${SOURCES})

常用 CMake 命令和变量

重要命令

  • project(): 定义项目

  • add_executable(): 添加可执行目标

  • add_library(): 添加库目标

  • target_link_libraries(): 链接库

  • include_directories(): 添加头文件路径

  • find_package(): 查找外部包

常用变量

  • CMAKE_SOURCE_DIR: 根源码目录

  • CMAKE_BINARY_DIR: 构建目录

  • CMAKE_CXX_COMPILER: C++ 编译器

  • CMAKE_CXX_FLAGS: 编译标志

  • PROJECT_NAME: 项目名称

  • CMAKE_BUILD_TYPE: 构建类型 (Debug/Release)

实际开发工作流

1. 首次构建

bash

mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug
make

2. 重新构建(修改代码后)

bash

make                # 在 build 目录中

3. 重新配置(修改 CMakeLists.txt 后)

bash

cmake ..            # 重新生成构建系统
make

4. 清理构建

bash

# 方法1:删除构建目录
rm -rf build# 方法2:在构建目录中清理
make clean

高级特性示例

查找和使用外部库

cmake

# 查找 OpenCV
find_package(OpenCV REQUIRED)# 包含头文件
include_directories(${OpenCV_INCLUDE_DIRS})# 链接库
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})

条件编译

cmake

option(USE_OPENMP "Use OpenMP for parallelization" ON)if(USE_OPENMP)find_package(OpenMP)if(OpenMP_CXX_FOUND)target_link_libraries(${PROJECT_NAME} OpenMP::OpenMP_CXX)endif()
endif()

添加测试

cmake

# 启用测试
enable_testing()# 添加测试
add_test(NAME MyTest COMMAND ${PROJECT_NAME})

实用技巧

  1. 指定编译器

    bash

    cmake .. -DCMAKE_CXX_COMPILER=g++-9
  2. 指定构建类型

    bash

    cmake .. -DCMAKE_BUILD_TYPE=Release
  3. 查看详细输出

    bash

    make VERBOSE=1
  4. 并行编译

    bash

    make -j4
  5. 安装程序

    bash

    make install

与 Makefile 对比的优势

  • 跨平台: 可生成 VS 项目、Xcode 项目、Makefile 等

  • 依赖管理: 自动处理头文件依赖

  • 模块化: 更好的项目结构管理

  • 生态系统: 大量现成的 Find 模块

  • 配置灵活: 支持条件编译、选项设置

总结

CMake 的基本使用流程:

  1. 编写 CMakeLists.txt

  2. 生成cmake 生成构建系统

  3. 编译make 或其他构建工具

  4. 运行: 执行生成的可执行文件

其他常考面试题

 Q:Makefile和CMake的区别?

A:

  • Makefile: 直接指定构建规则,语法相对简单,但跨平台性差

  • CMake: 生成器,根据CMakeLists.txt生成对应平台的构建文件(Makefile、Visual Studio项目等)

  • 现代趋势: CMake因其跨平台性和更好的依赖管理而更受欢迎

Q: 静态库和动态库的区别?

  • 静态库(.a): 编译时链接到可执行文件中,程序独立但体积大

  • 动态库(.so): 运行时加载,多个程序可共享,便于更新

Q: 头文件包含的两种方式?

A:

#include <iostream>    // 系统头文件,从系统路径查找
#include "myheader.h"  // 用户头文件,从当前目录开始查找
http://www.dtcms.com/a/576874.html

相关文章:

  • 使用房屋价格预测的场景,展示如何从多个影响因素计算权重和偏置的梯度
  • 企业网站的首页设计模板天津seo方案
  • 微服务之OpenFeign、hystrix熔断降级、loadbalancer负载均衡
  • 【微服务】(4) 负载均衡
  • 【Qt】Qt实践记录3——UDP通信
  • 考研408--计算机网络--day3--
  • 从云原生部署到智能时序分析:基于 Kubernetes 的 Apache IoTDB 集群实战与 TimechoDB 国产化增强特性深度解析
  • LLaVA-NeXT 学习笔记
  • 投资融资理财网站模板网站搭建福州公司
  • OpenStack创建实例一直处于创建且未分配IP问题解决
  • C++的诗行:一文掌握内存管理中 new/delete 接口正确调用与常见场景适配
  • 谷歌网站 百度做网站对服务器什么要求高
  • Smartproxy 企业级解决方案
  • 图像分类深度学习
  • 自监督骨干(DINOv2)用于内镜分割与跟踪的全面实现分析
  • 6.基础--SQL--DDL表操作-创建查询
  • 《算法闯关指南:优选算法--位运算》--34.判断字符是否唯一,35.丢失的数字
  • 四川建设网网站首页网站开发 周期
  • linux怎么检查磁盘是否有坏道
  • 微信小程序开发——第三章:WXML 与 WXSS —— 小程序页面结构与样式设计
  • Pytorch 内存布局优化:Contiguous Memory
  • pytorch-张量
  • MYSQL CDC 同步到 PAIMON
  • MATLAB实现高光谱分类算法
  • Linux:WSL常用指令总结
  • Git 最近提交中不小心包含了多余的文件怎么办
  • T100打破远程孤岛-轻松实现异地组网-P2P打洞+UDP NAT 穿透
  • 建设网站人员名单企业网站建设报价单
  • 联通研究院:基于‘多模态SCA+全周期协同’的中间件开源风险治理实践
  • 五子棋项目Alpha-Beta剪枝与MCTS+神经网络实现人机对弈算法对比报告