g++是GNU C++编译器的名称,是一种广泛使用的编程工具,用于将C++源代码编译为可执行的程序。g++是GNU Compiler Collection(GNU编译器集合)的一部分,由自由软件基金会(Free Software Foundation)开发和维护。
与C++代码一起使用的g++工具可以在多种操作系统上运行,包括Linux、macOS和Windows。它支持多种C++标准(如C++98、C++11、C++14等)和编译选项,包括生成调试信息、优化代码、生成目标平台的可执行文件等。
g++还支持多种输入格式,包括纯C++源代码、预编译头文件、汇编代码等,可以输出各种目标文件格式,例如ELF格式、Mach-O格式、PE格式等。g++还支持各种编译器插件,包括语法检查、代码优化、代码转换等,可以使用这些插件来增强编译器的功能和性能。
预处理:g++ -E main.cpp -o main.i
汇编:g++ -S main.i -o main.s
编译:g++ -c main.s -o main.o
链接:g++ main.o -o main.bin
g++ -E main.cpp -o main.i
#include "test.hpp"
#define Title "This is "
#define Add(a, b) a + b
int main()
{
const char *text = Title "Computer Vision";
int sum = Add(5, 9);
return 0;
}
int add(int a, int b);
int mul(int a, int b);
g++ -S main.i -o main.s
生成的main.s文件是C++源代码的汇编版本,包含汇编指令和数据,但还没有被编译成机器语言的二进制代码。该文件通常被称为汇编代码,是一个文本文件,可以用文本编辑器打开查看。
通过生成main.s文件,你可以检查编译器是否正确地将C++源代码转换为汇编代码,并且可以进一步分析和调试汇编代码。如果需要,你可以将main.s文件汇编为目标文件或可执行文件,最终得到可以在计算机上运行的程序。
int add(int a, int b);
int add1(int a, int b);
int add(int a, int b)
{
return a + b;
}
# 变量定义域 line 1 - line 7
# 定义变量var
var := folder
# 生成项是main.o, 依赖项是main.cpp
# main.cpp的修改时间比main.o新, 就会触发下面的command g++ -c main.cpp -o main.o
main.o : main.cpp # 依赖项定义域
g++ -c main.cpp -o main.o # command
#include
using namespace std;
int main()
{
cout << "Hello CUDA" << endl;
return 0;
}
cpp_srcs := $(shell find src -name "*.cpp")
cpp_objs := $(patsubst %.cpp,%.o,$(cpp_srcs))
cpp_objs := $(subst src/,objs/,$(cpp_objs))
debug :
@echo $(cpp_objs)
cpp_srcs := $(shell find src -name "*.cpp")
cpp_objs := $(patsubst %.cpp,%.o,$(cpp_srcs))
cpp_objs := $(subst src/,objs/,$(cpp_objs))
debug :
@echo $(cpp_objs)
# 定义cpp源码路径,并转换为objs目录先的o文件
cpp_srcs := $(shell find src -name "*.cpp")
cpp_objs := $(patsubst %.cpp,%.o,$(cpp_srcs))
cpp_objs := $(subst src/,objs/,$(cpp_objs))
# 定义cu源码路径,并转换为objs目录先的cuo文件
# 如果cpp文件和cu名字一样,把.o换成.cuo
cu_srcs := $(shell find src -name "*.cu") # 全部src下的*.cu存入变量cu_srcs
cu_objs := $(patsubst %.cu,%.cuo,$(cu_srcs)) # cu_srcs中全部.cu换成.o
cu_objs := $(subst src/,objs/,$(cu_objs)) # cu_objs src/换成objs/
# 定义名称参数
workspace := workspace
binary := pro
# makefile中定义cpp的编译方式
# $@:代表规则中的目标文件(生成项)
# $<:代表规则中的第一个依赖文件
# $^:代表规则中的所有依赖文件,以空格分隔
# $?:代表规则中所有比目标文件更新的依赖文件,以空格分隔
# 定义cpp文件的编译方式
# @echo Compile $< 输出正在编译的源文件的名称
objs/%.o : src/%.cpp
@mkdir -p $(dir $@)
@echo Compile $<
@g++ -c $< -o $@
# 定义.cu文件的编译方式
objs/%.cuo : src/%.cu
@mkdir -p $(dir $@)
@echo Compile $<
@nvcc -c $< -o $@
# 定义workspace/pro文件的编译
$(workspace)/$(binary) : $(cpp_objs) $(cu_objs)
@mkdir -p $(dir $@)
@echo Link $^
@g++ $^ -o $@
# 定义pro快捷编译指令,这里只发生编译,不执行
# 快捷指令就是make pro
pro : $(workspace)/$(binary)
# 定义指令并且执行的指令,并且执行目录切换到workspace下
run : pro
@cd $(workspace) && ./$(binary)
debug :
@echo $(cpp_objs)
@echo $(cu_objs)
这里报错了,因为缺少了cuda的库文件,下面是查看自己cuda版本和找到在哪里的指令,以我的CUDA11.7为例, 去到目录下看看有什么库文件,我们当前需要一个cudaruntime的头文件
nvcc --version
whereis cuda-11.7
cuda-11: /usr/local/cuda-11.7
cd /usr/local/cuda-11.7/lib64
来看看最后要完成的工程目录
project/
- src/
- main.cpp
- 01.kernel.cu
- objs/
- workspace/
- Makefile
# 定义cpp源码路径,并转换为objs目录先的o文件
cpp_srcs := $(shell find src -name "*.cpp")
cpp_objs := $(patsubst %.cpp,%.o,$(cpp_srcs))
cpp_objs := $(subst src/,objs/,$(cpp_objs))
# 定义cu源码路径,并转换为objs目录先的cuo文件
# 如果cpp文件和cu名字一样,把.o换成.cuo
cu_srcs := $(shell find src -name "*.cu") # 全部src下的*.cu存入变量cu_srcs
cu_objs := $(patsubst %.cu,%.cuo,$(cu_srcs)) # cu_srcs中全部.cu换成.o
cu_objs := $(subst src/,objs/,$(cu_objs)) # cu_objs src/换成objs/
workspace := workspace
binary := pro
# 定义头文件库文件和链接目标,后面用foreach一次性增加
include_paths := /usr/local/cuda-11.7/include
library_paths := /usr/local/cuda-11.7/lib64
link_librarys := cudart
# 定义编译选项
cpp_compile_flags := -m64 -fPIC -g -O0 -std=c++11
cu_compile_flags := -m64 -g -O0 -std=c++11
-m64:表示编译器生成的代码是 64 位的。
-fPIC:表示编译器要生成位置独立的代码。
-g:表示编译器会在生成的目标文件中加入调试信息,方便进行调试。
-O0:表示关闭优化。
-std=c++11:表示采用 C++11 标准进行编译。
rpath := $(foreach item,$(link_librarys),-Wl,-rpath=$(item))
include_paths := $(foreach item,$(include_paths),-I$(item))
library_paths := $(foreach item,$(library_paths),-L$(item))
link_librarys := $(foreach item,$(link_librarys),-l$(item))
cpp_compile_flags += $(include_paths)
cu_compile_flags += $(include_paths)
link_flags := $(rpath) $(library_paths) $(link_librarys)
# 定义cpp文件的编译方式
# @echo Compile $< 输出正在编译的源文件的名称
objs/%.o : src/%.cpp
@mkdir -p $(dir $@)
@echo Compile $<
@g++ -c $< -o $@ $(cpp_compile_flags)
# 定义.cu文件的编译方式
objs/%.cuo : src/%.cu
@mkdir -p $(dir $@)
@echo Compile $<
@nvcc -c $< -o $@ $(cu_compile_flags)
# 定义workspace/pro文件的编译
$(workspace)/$(binary) : $(cpp_objs) $(cu_objs)
@mkdir -p $(dir $@)
@echo Link $^
@g++ $^ -o $@ $(link_flags) -L./objs
# 定义pro快捷编译指令,这里只发生编译,不执行
# 快捷指令就是make pro
pro : $(workspace)/$(binary)
# 定义指令并且执行的指令,并且执行目录切换到workspace下
run : pro
@cd $(workspace) && ./$(binary)
debug :
@echo $(cpp_objs)
@echo $(cu_objs)
clean :
@rm -rf objs $(workspace)/$(binary)
# 指定伪标签,作为指令
.PHONY : clean debug run pro
# 定义cpp源码路径,并转换为objs目录先的o文件
cpp_srcs := $(shell find src -name "*.cpp")
cpp_objs := $(patsubst %.cpp,%.o,$(cpp_srcs))
cpp_objs := $(subst src/,objs/,$(cpp_objs))
# 定义cu源码路径,并转换为objs目录先的cuo文件
# 如果cpp文件和cu名字一样,把.o换成.cuo
cu_srcs := $(shell find src -name "*.cu") # 全部src下的*.cu存入变量cu_srcs
cu_objs := $(patsubst %.cu,%.cuo,$(cu_srcs)) # cu_srcs中全部.cu换成.o
cu_objs := $(subst src/,objs/,$(cu_objs)) # cu_objs src/换成objs/
# 定义名称参数
workspace := workspace
binary := pro
# 定义头文件库文件和链接目标,后面用foreach一次性增加
include_paths := /usr/local/cuda-11.7/include
library_paths := /usr/local/cuda-11.7/lib64
link_librarys := cudart
# 定义编译选项
cpp_compile_flags := -m64 -fPIC -g -O0 -std=c++11
cu_compile_flags := -m64 -g -O0 -std=c++11
# 对头文件, 库文件,目标统一增加 -I,-L-l
rpath := $(foreach item,$(link_librarys),-Wl,-rpath=$(item))
include_paths := $(foreach item,$(include_paths),-I$(item))
library_paths := $(foreach item,$(library_paths),-L$(item))
link_librarys := $(foreach item,$(link_librarys),-l$(item))
# 合并选项
# 合并完选项后就可以给到编译方式里面去了
cpp_compile_flags += $(include_paths)
cu_compile_flags += $(include_paths)
link_flags := $(rpath) $(library_paths) $(link_librarys)
# makefile中定义cpp的编译方式
# $@:代表规则中的目标文件(生成项)
# $<:代表规则中的第一个依赖文件
# $^:代表规则中的所有依赖文件,以空格分隔
# $?:代表规则中所有比目标文件更新的依赖文件,以空格分隔
# 定义cpp文件的编译方式
# @echo Compile $< 输出正在编译的源文件的名称
objs/%.o : src/%.cpp
@mkdir -p $(dir $@)
@echo Compile $<
@g++ -c $< -o $@ $(cpp_compile_flags)
# 定义.cu文件的编译方式
objs/%.cuo : src/%.cu
@mkdir -p $(dir $@)
@echo Compile $<
@nvcc -c $< -o $@ $(cu_compile_flags)
# 定义workspace/pro文件的编译
$(workspace)/$(binary) : $(cpp_objs) $(cu_objs)
@mkdir -p $(dir $@)
@echo Link $^
@g++ $^ -o $@ $(link_flags) -L./objs
# 定义pro快捷编译指令,这里只发生编译,不执行
# 快捷指令就是make pro
pro : $(workspace)/$(binary)
# 定义指令并且执行的指令,并且执行目录切换到workspace下
run : pro
@cd $(workspace) && ./$(binary)
debug :
@echo $(cpp_objs)
@echo $(cu_objs)
clean :
@rm -rf objs $(workspace)/$(binary)
# 指定伪标签,作为指令
.PHONY : clean debug run pro