如何通过CMake将Go代码编译为共享库并链接至C++项目
没问题!我来帮你把这个流程用CMake完整实现出来,分两个核心环节:先用CMake调用Go编译生成C共享库,再把你的C++代码和这个库链接起来。
假设你的项目结构是这样的
project-root/ ├── cmd/ │ └── c-mock-server/ │ └── main.go # 你的Go源文件(带C导出函数) ├── cpp/ │ └── main.cpp # 你的C++主程序 └── CMakeLists.txt # 我们要写的CMake配置文件
第一步:用CMake生成Go C共享库
CMake本身没有内置Go编译支持,但我们可以用add_custom_command和add_custom_target来调用Go的命令行工具完成编译。在根目录的CMakeLists.txt里添加以下内容:
cmake_minimum_required(VERSION 3.18) project(GoCppIntegration) # 1. 配置Go编译相关参数 set(GO_CMD go) # 如果Go不在系统PATH里,改成绝对路径比如/usr/local/go/bin/go set(GO_BUILD_FLAGS -buildmode=c-shared) # 生成的共享库和头文件会放在CMake构建目录下(比如build/) set(GO_SHARED_LIB ${CMAKE_BINARY_DIR}/cas${CMAKE_SHARED_LIBRARY_SUFFIX}) set(GO_HEADER_FILE ${CMAKE_BINARY_DIR}/cas.h) # 指定你的Go源文件路径 set(GO_SOURCE ${CMAKE_SOURCE_DIR}/cmd/c-mock-server/main.go) # 2. 自定义命令:调用Go编译生成C共享库和头文件 add_custom_command( OUTPUT ${GO_SHARED_LIB} ${GO_HEADER_FILE} COMMAND ${GO_CMD} build ${GO_BUILD_FLAGS} -o ${GO_SHARED_LIB} ${GO_SOURCE} DEPENDS ${GO_SOURCE} COMMENT "Compiling Go code into C shared library..." ) # 3. 自定义目标:让CMake默认构建这个Go库 add_custom_target(GoSharedLib ALL DEPENDS ${GO_SHARED_LIB} ${GO_HEADER_FILE})
代码解释:
CMAKE_SHARED_LIBRARY_SUFFIX是CMake的内置变量,会自动适配平台:Linux是.so,macOS是.dylib,Windows是.dll,实现跨平台兼容。ALL参数让这个Go库目标在默认构建流程中被执行,不用手动单独调用。DEPENDS ${GO_SOURCE}确保当你的Go源文件修改时,CMake会自动重新编译库。
第二步:CMake链接C++代码到Go共享库
接下来在同一个CMakeLists.txt里添加C++项目的配置,把生成的Go库链接进去:
# 1. 添加C++可执行目标 add_executable(CppMain ${CMAKE_SOURCE_DIR}/cpp/main.cpp) # 2. 确保先编译Go库,再编译C++代码 add_dependencies(CppMain GoSharedLib) # 3. 让C++代码能找到Go生成的头文件(cas.h) target_include_directories(CppMain PRIVATE ${CMAKE_BINARY_DIR}) # 4. 链接Go共享库 target_link_directories(CppMain PRIVATE ${CMAKE_BINARY_DIR}) target_link_libraries(CppMain PRIVATE cas)
关键注意点:
add_dependencies是必须的,它保证CMake的构建顺序:先完成Go库的编译,再编译和链接C++代码。target_include_directories要包含CMake构建目录,因为Go编译时会把cas.h生成在那里,你的C++代码需要#include "cas.h"来调用Go导出的函数。
你的C++代码示例(参考)
比如cpp/main.cpp可以这样写(对应Go导出的函数):
#include <iostream> #include "cas.h" int main() { // 调用Go导出的函数 char* msg = HelloFromGo(); std::cout << "Received from Go: " << msg << std::endl; // 注意:Go的C.CString分配的内存需要用Go的free函数释放 free(msg); return 0; }
如何构建运行
- 创建一个构建目录并进入:
mkdir build && cd build
- 生成构建文件:
cmake ..
- 编译项目:
make # 或者ninja,取决于你用的CMake生成器
- 运行C++程序:
./CppMain
额外小提示
- 如果你的Go项目使用Go Modules,确保在
add_custom_command里加上WORKING_DIRECTORY参数指定到Go模块的根目录,比如:add_custom_command( # ... 其他参数不变 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/cmd/c-mock-server ) - Windows平台下,Go生成的
.dll对应的导入库是.dll.a,CMake会自动处理链接,不用额外配置。
内容的提问来源于stack exchange,提问作者RaccoonH
相关产品推荐
相关产品推荐

