macOS + VSCode 环境下编译运行 C++ 项目完整指南(以 Modbus TCP 通信为例)
本文以一个通过 Modbus TCP 协议与 PLC 通信的 C++ 项目为例,从零开始搭建 macOS 上的 C++ 开发环境,涵盖工具安装、第三方库引入、CMake 自动化构建等内容。适合 C++ 初学者和从其他语言转过来的开发者。
一、环境准备
1.1 操作系统与硬件
- macOS(本文基于 Apple Silicon M 系列芯片,Intel Mac 需调整部分路径)
- VSCode 编辑器
1.2 安装 Homebrew
Homebrew 是 macOS 上的包管理器,相当于 Ubuntu 的 apt、Python 的 pip。如果还没安装过,打开终端执行:
bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
安装完成后验证:
bash
brew --version
1.3 安装编译工具链
bash
# C++ 编译器(macOS 自带 clang,也可以安装 gcc)
xcode-select --install
# CMake 构建工具
brew install cmake
# pkg-config(用于自动查找第三方库的路径)
brew install pkg-config
1.4 安装第三方库(以 libmodbus 为例)
bash
brew install libmodbus
安装完成后,Homebrew 会把文件放在以下位置(M 系列 Mac):
| 文件类型 | 路径 |
|---|---|
| 头文件 | /opt/homebrew/include/modbus/modbus.h(通过 pkg-config 以 #include <modbus.h> 引用) |
| 库文件 | /opt/homebrew/lib/libmodbus.dylib |
| pkg-config 配置 | /opt/homebrew/lib/pkgconfig/libmodbus.pc |
注意 :Intel Mac 的路径是
/usr/local/而非/opt/homebrew/。
二、手动编译(快速验证)
如果只是想快速编译单个文件,可以直接在终端执行:
bash
g++ -o my_program my_program.cpp \
-I/opt/homebrew/include \
-L/opt/homebrew/lib \
-lmodbus
参数说明:
| 参数 | 含义 |
|---|---|
-o my_program |
输出的可执行文件名 |
-I/opt/homebrew/include |
告诉编译器去哪里找头文件 |
-L/opt/homebrew/lib |
告诉链接器去哪里找库文件 |
-lmodbus |
链接 libmodbus 库 |
运行:
bash
./my_program
这种方式的缺点是每次编译都要手动输入一长串路径参数,容易出错,也不便于管理多文件项目。
三、使用 CMake 自动化构建(推荐)
3.1 什么是 CMake
CMake 是一个跨平台的构建管理工具。你只需要写一个 CMakeLists.txt 配置文件,告诉它"项目用了什么库",CMake 会自动找到库的路径并生成编译指令。配置一次,终身受益。
3.2 项目目录结构
testPLCbyCPP/
├── CMakeLists.txt # 构建配置文件(只需写一次)
├── test_f20_09.cpp # 测试程序 1
├── test_f20_12.cpp # 测试程序 2(后续新增)
├── test_xxx.cpp # 更多测试程序(后续新增)
└── build/ # 编译输出目录(自动生成)
├── test_f20_09 # 可执行文件 1
├── test_f20_12 # 可执行文件 2
└── ...
3.3 编写 CMakeLists.txt
在项目根目录创建 CMakeLists.txt,内容如下:
cmake
cmake_minimum_required(VERSION 3.10)
project(testPLCbyCPP)
set(CMAKE_CXX_STANDARD 17)
# 自动查找 libmodbus
find_package(PkgConfig REQUIRED)
pkg_check_modules(MODBUS REQUIRED libmodbus)
# 自动查找当前目录下所有 .cpp 文件
# 每个 .cpp 文件编译为一个独立的可执行文件
file(GLOB ALL_SOURCES "*.cpp")
foreach(SOURCE_FILE ${ALL_SOURCES})
get_filename_component(EXEC_NAME ${SOURCE_FILE} NAME_WE)
add_executable(${EXEC_NAME} ${SOURCE_FILE})
target_include_directories(${EXEC_NAME} PRIVATE ${MODBUS_INCLUDE_DIRS})
target_link_directories(${EXEC_NAME} PRIVATE ${MODBUS_LIBRARY_DIRS})
target_link_libraries(${EXEC_NAME} ${MODBUS_LIBRARIES})
endforeach()
逐行解释:
cmake_minimum_required:指定最低 CMake 版本project:项目名称set(CMAKE_CXX_STANDARD 17):使用 C++17 标准find_package(PkgConfig REQUIRED):启用 pkg-config 工具pkg_check_modules(MODBUS REQUIRED libmodbus):通过 pkg-config 自动查找 libmodbus 的头文件路径、库路径、库名称,分别存入MODBUS_INCLUDE_DIRS、MODBUS_LIBRARY_DIRS、MODBUS_LIBRARIES变量file(GLOB ALL_SOURCES "*.cpp"):扫描当前目录下所有.cpp文件foreach循环:为每个.cpp文件创建一个同名的可执行文件,并自动设置好头文件路径和库链接
3.4 编译与运行
bash
# 进入项目目录
cd testPLCbyCPP
# 创建并进入 build 目录(首次执行)
mkdir build && cd build
# 生成编译配置(首次执行,或 CMakeLists.txt 改动后执行)
cmake ..
# 编译
make
# 运行
./test_f20_09
正常输出示例:
-- Found PkgConfig: /opt/homebrew/bin/pkg-config (found version "2.5.1")
-- Checking for module 'libmodbus'
-- Found libmodbus, version 3.1.11
-- Configuring done
-- Generating done
[ 50%] Building CXX object CMakeFiles/test_f20_09.dir/test_f20_09.cpp.o
[100%] Linking CXX executable test_f20_09
[100%] Built target test_f20_09
3.5 日常开发工作流
| 场景 | 操作 |
|---|---|
修改了已有的 .cpp 文件 |
在 build 目录执行 make |
新增了一个 .cpp 文件 |
在 build 目录执行 cmake .. && make |
修改了 CMakeLists.txt |
在 build 目录执行 cmake .. && make |
| 想清理重新编译 | 删除 build 目录,重新 mkdir build && cd build && cmake .. && make |
四、VSCode 集成
4.1 推荐安装的扩展
在 VSCode 扩展商店搜索安装以下扩展:
- C/C++(Microsoft 出品):代码高亮、智能提示、调试
- CMake Tools(Microsoft 出品):CMake 项目集成,支持一键编译运行
4.2 使用 CMake Tools 扩展
安装 CMake Tools 后,VSCode 底部状态栏会出现 CMake 相关按钮:
- 打开项目文件夹(包含
CMakeLists.txt的目录) - 按
Cmd+Shift+P,输入CMake: Configure,选择编译器(通常选 Clang) - 按
Cmd+Shift+P,输入CMake: Build,或直接点击底部状态栏的 Build 按钮 - 在终端中执行
./build/test_f20_09运行
4.3 配置头文件路径提示(消除红色波浪线)
如果 VSCode 的 IntelliSense 对 #include <modbus.h> 报红色波浪线(找不到头文件),在项目根目录创建 .vscode/c_cpp_properties.json:
json
{
"configurations": [
{
"name": "Mac",
"includePath": [
"${workspaceFolder}/**",
"/opt/homebrew/include/modbus"
],
"defines": [],
"macFrameworkPath": [
"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks"
],
"compilerPath": "/usr/bin/clang",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "macos-clang-arm64"
}
],
"version": 4
}
Intel Mac 用户需将
intelliSenseMode改为macos-clang-x64,includePath中的/opt/homebrew/include改为/usr/local/include。
五、常见问题排查
5.1 fatal error: 'modbus.h' file not found
原因 :头文件路径不对。libmodbus 的 pkg-config 配置(Cflags: -I.../include/modbus)会将 include 路径直接指向 modbus/ 子目录,所以代码中应使用 #include <modbus.h>,而非 #include <modbus/modbus.h>。
解决 :确认代码中使用 #include <modbus.h>,并确保 cmake 通过 pkg_check_modules 拿到了正确的 include 路径。
5.2 zsh: command not found: cmake
原因:没有安装 CMake。
解决 :执行 brew install cmake。
5.3 zsh: command not found: pkg-config
原因:没有安装 pkg-config。
解决 :执行 brew install pkg-config。
5.4 clang: warning: overriding deployment version from '16.0' to '26.0'
原因:编译器的目标系统版本设置不一致,不影响功能。
解决 :可以忽略,或在 CMakeLists.txt 中加一行消除警告:
cmake
set(CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "" FORCE)
5.5 链接错误 ld: library 'modbus' not found
原因:链接器找不到 libmodbus 库文件。
解决 :确认 libmodbus 已安装(brew list libmodbus),然后使用 CMake 的 pkg_check_modules 自动查找,或手动指定 -L/opt/homebrew/lib。
六、完整示例代码
以下是一个通过 Modbus TCP 向 PLC 发送指令并等待执行完成的完整示例:
cpp
#include <modbus.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
int main() {
// 1. 连接 PLC
const char* PLC_IP = "192.168.1.200";
modbus_t* ctx = modbus_new_tcp(PLC_IP, 502);
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "连接失败: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
printf("连接成功!\n");
// 2. 写入参数到 Modbus 寄存器
uint16_t value = 42;
modbus_write_register(ctx, 50900, value);
printf("已写入参数: %d → 地址 50900\n", value);
// 3. 发送启动信号
uint16_t action_id = 1;
modbus_write_register(ctx, 50009, action_id);
printf("已发送启动信号: action_id=%d\n", action_id);
// 4. 轮询等待完成信号
uint16_t result = 0;
while (result != action_id) {
sleep(1);
modbus_read_registers(ctx, 50059, 1, &result);
printf("等待中... G_F20_End[9] = %d\n", result);
}
printf("执行完成!\n");
// 5. 清除启动信号
modbus_write_register(ctx, 50009, 0);
// 6. 断开连接
modbus_close(ctx);
modbus_free(ctx);
return 0;
}
七、总结
| 方式 | 适用场景 | 命令 |
|---|---|---|
| 手动 g++ 编译 | 临时测试单个文件 | g++ -o out file.cpp -I... -L... -l... |
| CMake 构建 | 正式项目开发 | cmake .. && make |
| VSCode + CMake Tools | 日常开发体验最佳 | 点击按钮或 Cmd+Shift+P |
核心要点 :用 CMake 管理项目,配置一次 CMakeLists.txt,以后新增 .cpp 文件只需 cmake .. && make,不用手动指定任何路径。