编辑
2024-07-20
编程语言
00
请注意,本文编写于 182 天前,最后修改于 179 天前,其中某些信息可能已经过时。

目录

C++ 代码编译与构建过程
Go 代码编译与构建过程
对比总结
示例代码与命令
关于交叉编译
C++交叉编译
工具链
示例:在Linux上为ARM编译
示例:在Linux上为Windows编译
Go交叉编译
设置环境变量
示例:在Linux上为Windows编译
示例:在Linux上为ARM编译
对比与总结

C++与Go系列之编译篇

Linux系统下自带C++编译工具g++,而Go的编译工具需要安装。

写在前面

1.Ubuntu安装最新版本的稳定版 golang-go 可以通过 snap sudo snap install go --classic

如果snap不存在,通过以下命令安装进行按照:sudo apt install snapd

如果要查看snap支持安装的版本:snap info go

2.Ubuntu安装最新版本的golang-go也可以通过PPA,需要先添加PPA源 sudo add-apt-repository ppa:longsleep/golang-backports

然后执行安装命令 sudo apt-get install golang-go

如果要安装指定版本sudo apt-get install golang-1.11-go

如果add-apt-repository不存在,通过以下命令安装进行按照:sudo apt-get install software-properties-common

如果要查看支持安装的版本:apt-cache madison golang-go

3.一般安装完go后还需要设置模块包代理地址: go env -w GOPROXY=https://goproxy.cn,direct 查看是否设置成功: go env | grep GOPROXY

C++ 代码编译与构建过程

  1. 源文件编写

    • C++源文件通常以.cpp.h.hpp等扩展名保存。
  2. 预处理(Preprocessing)

    • 预处理器指令(如#include#define)在这一阶段处理。
    • 预处理的输出是一个纯文本文件,没有预处理器指令。
  3. 编译(Compilation)

    • 将预处理后的代码转换为汇编代码。
    • 每个源文件都会生成一个对应的汇编文件(.s)。
  4. 汇编(Assembly)

    • 汇编代码转换为机器码,生成目标文件(.o.obj)。
    • 目标文件包含二进制代码,但还不是可执行文件。
  5. 链接(Linking)

    • 将所有目标文件和所需的库文件链接在一起,生成最终的可执行文件。
    • 静态链接:将所有依赖的库静态嵌入可执行文件。
    • 动态链接:将依赖库在运行时动态加载。
  6. 构建系统

    • 使用构建系统(如Make、CMake、Ninja)来管理和自动化编译与链接过程。

Go 代码编译与构建过程

  1. 源文件编写

    • Go源文件以.go扩展名保存。
  2. 导入包(Importing Packages)

    • import语句用于导入标准库或第三方库。
  3. 编译(Compilation)

    • Go编译器将所有的Go文件编译成中间代码。
    • 所有依赖包在编译时会被解析和编译。
  4. 链接(Linking)

    • 将所有中间代码和所需的库链接成一个单一的可执行文件。
    • Go使用静态链接,所有依赖库都嵌入到可执行文件中。
  5. 构建工具

    • Go有内置的构建工具,如go buildgo installgo run
    • go build:编译包及其依赖项,但不安装结果。
    • go install:编译并安装包。
    • go run:编译并运行Go程序。

对比总结

  1. 编译过程
    • C++有多个独立的阶段(预处理、编译、汇编、链接),而Go的编译过程更简化,直接从源码到可执行文件。
  2. 构建系统
    • C++常用第三方构建系统,如Make、CMake,Go则使用内置工具,简化了构建过程。当然,Make也可以用于构建Go项目
  3. 依赖管理
    • C++的依赖管理通常通过手动配置或使用包管理器(如vcpkg、Conan)。
    • Go有内置的模块管理系统(Go Modules),方便依赖管理。

示例代码与命令

C++ 构建示例

cpp
// main.cpp #include <iostream> int main() { std::cout << "Hello, World!" << std::endl; return 0; }
bash
g++ -o hello main.cpp ./hello

Go 构建示例

go
// main.go package main import "fmt" func main() { fmt.Println("Hello, World!") }
bash
go build -o hello main.go ./hello

编译后的文件比对(编译器版本不同可能编译出来的大小不一样),其hello_cpp采用动态链接libstdc++.so:

root@ubuntu:~/cpp-go# ls -alh total 1.9M drwxr-xr-x 2 root root 4.0K Jul 21 10:19 . drwxr-xr-x 6 root root 4.0K Jul 20 23:07 .. -rwxr-xr-x 1 root root 9.7K Jul 20 23:08 hello_cpp -rw-r--r-- 1 root root 97 Jul 20 23:07 hello_cpp.cpp -rwxr-xr-x 1 root root 1.9M Jul 21 10:19 hello_go -rw-r--r-- 1 root root 77 Jul 20 23:07 hello_go.go

关于交叉编译

交叉编译(Cross-compilation)是指在一种平台上编译生成可在另一种平台上运行的二进制文件的过程。也就是说,在Linux上编译生成Windows的程序,或者在x86_64架构的Linux上编译生成适用于ARM64架构的Linux程序,都是要通过交叉编译。

C++交叉编译

工具链

C++交叉编译通常需要特定的工具链,例如gccg++的交叉编译版本。常见的工具链有:

  • arm-linux-gnueabi-g++:用于ARM架构的Linux系统。
  • x86_64-w64-mingw32-g++:用于64位的Windows系统。
示例:在Linux上为ARM编译
bash
arm-linux-gnueabi-g++ -o hello_arm main.cpp

如果还没有安装ARM交叉编译工具链,可以使用以下命令进行安装:

bash
sudo apt-get install g++-arm-linux-gnueabi
示例:在Linux上为Windows编译
bash
x86_64-w64-mingw32-g++ -o hello_windows.exe main.cpp

如果还没有安装Windows交叉编译工具链,可以使用以下命令进行安装:

bash
sudo apt-get install g++-mingw-w64

Go交叉编译

Go语言的交叉编译比C++要简单得多,因为Go编译器本身就支持多平台交叉编译。

设置环境变量

在Go中进行交叉编译,只需设置几个环境变量:

  • GOOS:目标操作系统,如linuxwindowsdarwin
  • GOARCH:目标架构,如amd64arm386
示例:在Linux上为Windows编译
bash
GOOS=windows GOARCH=amd64 go build -o hello_windows.exe main.go
示例:在Linux上为ARM编译
bash
GOOS=linux GOARCH=arm go build -o hello_arm main.go

对比与总结

  1. 工具链

    • C++需要特定的交叉编译工具链,如arm-linux-gnueabi-g++x86_64-w64-mingw32-g++
    • Go内置支持交叉编译,只需设置环境变量GOOSGOARCH
  2. 编译命令

    • C++需要安装并使用对应的交叉编译器。
    • Go通过内置支持,直接设置环境变量即可实现交叉编译。
  3. 配置简易性

    • C++的交叉编译配置相对复杂,需要了解并配置对应的工具链。
    • Go的交叉编译配置简单,编译过程更为直观。

本文作者:phae

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!