linux运行c++代码,jetson Orin nano上实验的
代码示例
为了方便就直接展示在VScode中,就不在终端中使用操作,终端操作跟VScode中操作是类似。
首先创建一个多目录下的文件夹,如下面图片
上面图片中的代码
main.cpp
#include <iostream>
#include "../s1/support1.h"
#include "../s2/support2.h"
int main()
{
std::cout << "Hello from my project!" << std::endl;
Support1 mys1;
mys1.s1();
Support2 mys2;
mys2.s2();
std::cin.get();
}
support1.h
class Support1
{
public:
void s1();
};
support1.cpp
#include <iostream>
#include "support1.h"
void Support1::s1()
{
std::cout << "hello support1" << std::endl;
}
support2.h
class Support2
{
public:
void s2();
};
support2.cpp
#include <iostream>
#include "support2.h"
void Support2::s2()
{
std::cout<<"hello support2"<<std::endl;
}
g++运行代码,不使用VScode(多目录)
不使用makefile
首先在终端中使用下面命令,下面命令主要是将support1.cpp生成一个编译单元,输出为support1.o
g++ -g -c -o ./s1/support1.o ./s1/support1.cpp
结果如下图所示,在s1文件下多出了一个support1.o文件
其中-c
表示生成编译单元,也就是输出.o
格式的文件
-o
后面跟的是输出的文件保存地址
同理,可以使用下面代码生成support2.o
文件,然后使用下面代码将所有的编译单元link起来,并编译main.cpp文件
# genenrate support2.o
g++ -g -c -o ./s2/support2.o ./s2/support2.cpp
# compile main.cpp, link support1.o support2.o
g++ -g -o mainProject/main.out mainProject/main.cpp s1/support1.o s2/support2.o
结果如下图所示
可以从上图看到已经有main.out
exe程序生成,只需要用终端打开文件目录,并输入下面代码,注意这个./
千万不能丢失,否则就会保错
./main.out
使用makefile
首先在mainProject
目录下创建一个makefile
文件,文件的内容,如下图所示
makefile
文件的内容如下,makefile的格式内容可以参考这个链接
project : ../s1/support1.o ../s2/support2.o
g++ main.cpp ../s1/support1.o ../s2/support2.o -g -o main.out
support1.o : ../s1/support1.cpp ../s1/support.h
g++ -g -c ../s1/support1.cpp
support2.o : ../s2/support2.cpp ../s2/support2.h
g++ -g -c ../s2/support2.cpp
然后在终端中使用make
,对makefile进行编译
编译的结果如下图所示,可以看到s1文件下有support1.o
文件,s2文件下有support2.o
文件,mainProject文件下有main.out
二进制程序,main.out
执行结果如下图所示
使用VScode和g++运行c++代码(多目录)
VScode环境配置,安装下面图片中的扩展库
不使用makefile
在按F5
运行main.cpp,第一次进行调试的时候会出现选择g++编译的情况,直接选择第一个g++编译器即可,
然后会运行失败,会出现下面图片中提示的错误,选择仍要调试
选项
然后会出现下面图片中的提示,选择打开"launch.json"
选项
然后会出现.vscode/tasks.json
文件和.vscode/launch.json
文件
对tasks.json
进行修改
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ 生成活动文件",
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-g", // 这个是编译程序的
"${file}",
"${fileDirname}/../s1/support1.cpp", // s1/support1.cpp文件
"${fileDirname}/../s2/support2.cpp", // 直接在这里添加需要g++的文件
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "调试器生成的任务。"
}
],
"version": "2.0.0"
}
修改完成后,直接再次按F5
,如果想要调试的话,可以直接和python一样打断点,如果不使用快捷键的话,可以使用VScode右上角的运行按钮选择是直接运行还是进行调试
选择调试后,结果会如下图所示
使用makefile
按照g++运行代码,不使用VScode(多目录)/使用makefile
章节的方法将makefile
文件添加好
然后根据使用VScode和g++运行c++代码(多目录)/不使用makefile
中的方法生成launch.json
和tasks.json
文件
此时的tasks.json
内容为
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ 生成活动文件",
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "调试器生成的任务。"
}
],
"version": "2.0.0"
}
launch.json
内容为
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": []
}
然后将tasks.json
修改为下面的内容,label
后面的名称可以是任意的字符串,如“myProject”,command
后面的是要执行的命令,需要cd mainProject
是因为项目在Hello Copy
这个文件目录下,而makefile
文件在mainProject
这个子文件夹下
{
"tasks": [
{
"label": "makeMyProject",
"type": "shell",
"command": "cd mainProject && make"
}
],
"version": "2.0.0"
}
在修改launch.json
之前,首先点击VScode右下角的添加配置
然后会出现下面的选项,选择第二个选项C/C++: (gdb) 启动
然后launch.json
的文件内容就变为下面的json
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动",
"type": "cppdbg",
"request": "launch",
"program": "输入程序名称,例如 ${workspaceFolder}/a.out",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "将反汇编风格设置为 Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
}
]
}
在上面的launch.json
的基础上进行修改,生成的可执行文件main.out
也在mainProject
文件夹下,所以launch.json
中还有一个program
需要更新下:"program": "${workspaceFolder}/mainProject/main.out"
,也就是指定.out的输出路径;还需要添加 "preLaunchTask": "makeMyProject",
注意这个 "preLaunchTask"
冒号后的内容一定要跟tasks.json
中的label
相同,至于"miDebuggerPath": "/usr/bin/gdb"
可能是可添加可不添加(也有可能是添加了这个才能对C++代码进行调试),我添加了,我看其他博客是没有添加这个,修改后的launch.json
如下
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/mainProject/main.out", // 修改
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "将反汇编风格设置为 Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
],
"preLaunchTask": "makeMyProject", // 添加
"miDebuggerPath": "/usr/bin/gdb" // 添加
}
]
}
然后使用F5
键进行运行,或者直接点击main.cpp
,然后选择运行——>启动调试
,会得到如下图,可以看到可以运行成功
makefile文件优化
现在有个问题,由于只有3个文件夹,3个cpp文件,所以在生成.out文件时候,使用了三个文件(一个.cpp,两个.o)来完成g++ myProject.cpp ../s1/support1.o ../s2/support2.o -g -o mainProject.out
。如果有很多文件?需要一个一个先把调用的文件编译了,然后一起link然后生成.out?并且添加一个文件就需要改变makefile文件?所以需要对makefile进行优化,不管.cpp文件在哪里,都拉过来链接成为.o文件,不管.o文件在哪里,都统统拉过来编译为.out文件
CC := g++
CFLAGS := -g
TARGET := main.out
SOURCE := $(wildcard *.cpp ../s1/*.cpp ../s2/*.cpp)
OBJS := $(patsubst %.cpp,%.o,$(SOURCE))
Tar : $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(TARGET)
%.o : %.cpp
$(CC) $(CFLAGS) -c $< -o $@
.PHONY : clean
clean :
rm -rf $(TARGET) *.o ../s1/*.o ../s2/*.o
使用了CC
作为变量名,变量内容为g++
。CFLAGS
同理,可以使用$(CC)
和$(CFLAGS)
的方式使用两个变量。使用SOURCE
表示源码的所有位置,由于makefile在mainProject文件夹下,所以文件路径就是当前文件夹下的所有.cpp文件,使用*通配所有后缀为.cpp的文件,以及同级的s1文件夹和s2文件夹的所有.cpp文件,如果只有文件发生变化,那么使用通配的方式还是能找到新增的文件,如果文件夹的位置发生变化或者新增,就需要更改这个SOURCE
变量。OBJS
是将通配出来的所有SOURCE
的后缀.cpp换成.o(通过函数patsubst
实现)。所以Tar这个命令就是利用所有的.o文件生成main.out,而.o文件需要%.o
这步生成。这里有$<
和$@
等符号介绍一下:
符号 | 含义 |
---|---|
$^ | 代表所有的依赖文件 |
$@ | 代表所有的目标文件 |
$< | 代表第一个依赖文件 |
$? | 所有比目标新的依赖文件名称的集合,以空格分隔 |
$+ | 很像$^,也是所有依赖文件的集合,但是它不去除重复的依赖 |
$* | 匹配目标模式中“%”之前的部分 |
$(CC) $(CFLAGS) -c $< -o $@
就是将所有的依赖cpp文件,生成所有的目标.o。
说一下.PHONY
的作用,.PHONY
后面写的是伪目标,也就是说这种目标只是占用一个符号一个名字而已,无论当前目录下是否有clean文件,不会对比是否最新,只要执行make clean
,clean目标下面定义的命令永远都会执行!在包含makefile的文件夹下执行make clean
就可以清除所有的.o以及.out文件。
可以看到,上面的makefile
优化成功了,但是并没有执行make clean
命令清除掉main.out、main.o、support1.o、support2.o
。如果要将执行make
之后生成的.o以及.out文件都删除了,必须在执行make
后,接着执行make clean
。
如下面终端中的,在执行make
后,生成了main.out、main.o
,然后执行make clean
后,又清除了main.out、main.o
文件。
其实也可以在VScode中清除main.o、support1.o、support2.o
,但是不能清除main.out
,否则会出现报错(open launch.json错误)。
具体可以在tasks.json
中的command
后"cd mainProject && make"
修改为"cd mainProject && make && make clean"
,如下所示
{
"tasks": [
{
"label": "makeMyProject",
"type": "shell",
"command": "cd mainProject && make && make clean"
}
],
"version": "2.0.0"
}
为了防止出现报错,修改makefile文件,将最后一行rm -rf $(TARGET) *.o ../s1/*.o ../s2/*.o
修改为rm -rf *.o ../s1/*.o ../s2/*.o
,这个$(TARGET)
其实就是main.out
。
将tasks.json
和makefile
修改好后,直接F5
键运行,由下图可以看到只有main.out
保存下来了
生成库文件的Makefile万能模板:
CC := g++
LD := ld
CFLAGS = -shared -fPIC -Wall -O -g
LDFLAGS := -shared -fPIC
SOURCE := $(wildcard *.cpp ./subpath1/*.cpp ./subpath2/*.cpp)
OBJS := $(patsubst %.cpp,%.o,$(SOURCE))
TARGET_LIB := main
makeso:
g++ $(SOURCE) -fPIC -shared -o $(TARGET_LIB)
all:$(OBJS)
echo $(OBJS)
$(CC) $(LDFLAGS) -o $(TARGET_LIB) $(OBJS)
%.o:%.cpp
@echo Compiling $< ...
$(CC) $(CFLAGS) -c $< -o $@
.PHONY: clean
clean:
rm *.so *.o ./subpath1/*.o ./subpath2/*.o $(TARGET_LIB) -rf
使用VScode引入依赖库(opencv、cuda库)等,以opencv为例
不使用makefile
方法一
创建tasks.json
和launch.json
文件这个就不做介绍了,前面已经做过介绍了,生成原始文件就可以,不需要进行任何改变,会在下文进行改变。
创建之后还需按照以下步骤生成c_cpp_properties.json
首先点击查看——>命令面板
然后会出现下面的界面,选择C/C++:编辑配置(JSON)
然后就会出现c_cpp_properties.json
,c_cpp_properties.json
的内容也如下:
需要对c_cpp_properties.json
的内容进行修改
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/include/opencv4" // jetson中opencv的头文件在这个路径中
// /usr/include/opencv4/opencv2
],
"defines": [],
"compilerPath": "/usr/bin/clang-8",
"cStandard": "c17",
"cppStandard": "c++14",
"intelliSenseMode": "linux-clang-arm64"
}
],
"version": 4
}
然后,需要对tasks.json
进行修改
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ 生成活动文件",
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"${fileDirname}/../s1/support1.cpp",
"${fileDirname}/../s2/support2.cpp",
"-o",
"${fileDirname}/${fileBasenameNoExtension}",
// "`pkg-config", "--cflags", "--libs", "opencv4`",
// 方法一中需要添加以下内容
"-I",
"/usr/include",
"-I",
"/usr/include/opencv4",
"-I",
"/usr/include/opencv4/opencv2",
/* 项目所需的库文件路径 */
"-L",
"/usr/lib",
/* OpenCV的lib库 在windows中可以直接使用opencv_world480.dll*/
"-l",
"opencv_core",
"-l",
"opencv_imgproc",
"-l",
"opencv_imgcodecs",
"-l",
"opencv_video",
"-l",
"opencv_ml",
"-l",
"opencv_highgui",
"-l",
"opencv_objdetect",
"-l",
"opencv_flann",
"-l",
"opencv_imgcodecs",
"-l",
"opencv_photo",
"-l",
"opencv_videoio"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "调试器生成的任务。"
}
],
"version": "2.0.0"
}
在进行修改之后,可以直接使用F5
进行运行
下面这张图片就是类似于g++编译代码
然后结果图是下面这张图
方法二
c_cpp_properties.json
跟方法一的一样
就只有tasks.json
的内容有所改变
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ 生成活动文件",
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"${fileDirname}/../s1/support1.cpp",
"${fileDirname}/../s2/support2.cpp",
"-o",
"${fileDirname}/${fileBasenameNoExtension}",
"`pkg-config", "--cflags", "--libs", "opencv4`" // 这里需要是添加的代码
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "调试器生成的任务。"
}
],
"version": "2.0.0"
}
pkg-config --cflags --libs opencv4
就是链接库,可以直接在终端使用该命令行,可以参考一下
Linux 下编译 OpenCV4
然后直接F5
键进行调试
下面这张图片就是类似于g++编译代码
然后结果图是下面这张图
使用makefile
基础的makefile文件创建可以参考使用VScode和g++运行c++代码(多目录)/makefile文件优化
,然后对makefile
文件进行修改,
CC := g++
CFLAGS := -g
LDLIBS = `pkg-config --cflags --libs opencv4` # 添加了这个,这个就是链接到opencv库和头文件
TARGET := main.out
SOURCE := $(wildcard *.cpp ../s1/*.cpp ../s2/*.cpp)
OBJS := $(patsubst %.cpp,%.o,$(SOURCE))
Tar : $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(TARGET) $(LDLIBS) # 这里添加 $(LDLIBS)
%.o : %.cpp
$(CC) $(CFLAGS) -c $< -o $@ $(LDLIBS) # 这里添加了$(LDIIBS)
.PHONY : clean
clean :
rm -rf *.o ../s1/*.o ../s2/*.o
然后直接F5
键进行调试
下面这张图片就是类似于g++编译代码
然后结果图是下面这张图也可以进行断点调试