Linux下C++開發
Linux 系統介紹
簡介
Linux
屬于多用戶多任務
操作系統,而Windows
屬于單用戶多任務
操作系統Linux
一切皆文件- 目錄結構
- bin 存儲二進制可執行文件
- dev 存放的是外接設備,例如磁盤,光盤等。在其中的外接設備是不能直接被使用的,需要
掛載
- etc 主要存儲一些配置文件
- home 表示
除了root用戶以外
,其它用戶的家目錄,類似于Windows
下的User/用戶目錄
- proc 全稱
process
,表示進程,該目錄存儲的是Linux
運行時候的進程 - root 該目錄是
root
用戶自己的家目錄 - sbin 全稱
super binary
,該目錄也存儲一些可被執行的二進制文件,但必須得有super
權限的用戶才能執行 - tmp 當系統運行時候產生的
臨時
文件會存放在這個目錄 - usr 存放的是用戶自己安裝的軟件。類似于
Windows
下的program files
- var 該目錄存放
程序/系統
的日志
文件 - mnt 當外接設備需要掛載的時候,就需要掛載在
mnt
目錄下
常用命令
time ./hello
測試hello
程序執行的時間ls -lah /home ./
以列表形式顯示多個目錄,-h
表示以可讀性較高的形式顯示mkdir -p a/b/c
表示一次性創建多層不存在的目錄mkdir a b c
創建多個目錄man
全稱an interface to the system reference manuals
- 作用:包含了
Linux
中全部命令手冊 man man
查看man
命令的手冊man ls
查看ls
命令的手冊
- 作用:包含了
reboot
立即重啟shutdown -h now
立即關機gedit a.txt
用可視化文本編輯器打開a.txt
常用快捷鍵
ctrl+l
清屏ctrl+c
退出當前行ctrl+w
刪除當前行一個單詞ctrl+shift+'+'
放大Terminal
【Ubuntu
】ctrl+'-'
縮小Terminal
【Ubuntu
】ctrl+'+'
放大Terminal
【Mingw64
】ctrl+'-'
縮小Terminal
【Mingw64
】ctrl+alt+t
開啟Terminal
安裝常用軟件
sudo apt update
安裝軟件前,最好更新軟件庫sudo apt install tree
安裝可以以樹形方式瀏覽多層目錄sudo apt install build-essential gdb
安裝好gcc,g++,gdb
- 查看是否安裝成功:
gcc --version
g++ --version
gdb --version
- 查看是否安裝成功:
sudo apt install cmake
安裝cmake
sudo apt install libboost-dev
安裝boost
開發環境搭建
GCC編譯器
- 編譯過程
- 預處理-Pre-Processing // .i文件
# -E 選項指示編譯器僅對輸入文件進行預處理 g++ -E test.cpp -o test.i // .i文件
- 編譯-Compiling // .s文件
# -S 選項告訴g++在為C++代碼產生了匯編語言文件后停止編譯 # g++ 產生的匯編語言的默認擴展名為 .s g++ -S test.i -o test.s
- 匯編-Assembling // .o文件
# -c 選項告訴g++僅把源代碼編譯為機器語言的目標代碼 # 默認情況下,g++建立的目標文件有一個 .o 的擴展名 g++ -c test.s -o test.o
- 鏈接-Linking // bin文件
# -o 選項指定將來的可執行文件的文件名 g++ test.o -o test
- g++重要的編譯參數
- -g 編譯帶
調試
信息的可執行文件# -g 選項告訴GCC產生能被GNU調試器GDB使用的調試信息,以調試程序 g++ -g test.cpp
- -O[n] 優化源代碼
# -O0 表示不做優化 # -Og 表示不做優化 【有些g++版本不支持】 # -O1 為默認優化 # -O2 除了完成-O1的優化之外,還進行一些額外的調整工作,如指令調整等 # -O3 包括循環展開和其它一些與處理特性相關的優化工作 g++ -O2 test.cpp
- -l 和 -L 指定庫文件 | 指定庫文件路徑
# -l參數(小寫) 指定程序要鏈接的庫名 # 在/lib和/usr/lib和/usr/local/lib里的庫直接用-l參數就能鏈接 g++ -glog test.cpp# 如果庫文件沒有放在/lib和/usr/lib和/usr/local/lib,需要使用-L參數(大寫)指定庫文件所在的目錄 g++ -L/home/balingshang/mylibfolder -lmylib test.cpp
- -I 指定頭文件搜索目錄
# /usr/include目錄一般不需要指定,g++知道去那里找 # 其它目錄需要自己指定 g++ -I/myinclude test.cpp
- -Wall 打印警告信息s
g++ -Wall test.cpp
- -w 關閉警告信息
g++ -w test.cpp
- -std=c++11 設置編譯標磚
# 使用 c++11 標準編譯 test.cpp g++ -std=c++11 test.cpp
- -o 指定輸出文件名
g++ test.cpp -o test
- -D 定義宏
# 在使用gcc/g++編譯的時候定義宏# 常用場景: # -DDEBUG定義DEBUG宏,可能文中有DEBUG宏部分的相關信息,用-DDEBUG來選擇開啟或者關閉DEBUG
#include <iostream> int main(int argc, char** argv) { #ifdef DEBUGstd::cout << "In Debug" << std::endl; #elsestd::cout << "Not In Debug" << std::endl; #endif } // 1. 在編譯的時候,使用 g++ -DDEBUG main.cpp // 2. 輸出:In Debug
- man g++ 查看其它編譯選項
man g++
- 生成靜態鏈接庫
g++ -c mylib.cpp
ar rs libmylib.a mylib.o
- 使用:
g++ main.cpp -lmylib -Lmylibfolder -Iinclude -o main
- 生成動態鏈接庫
g++ swap.cpp -Iinclude -fPIC -shared -o libswap.so
g++ main.cpp -lswap -Lmysharedlibfolder -Iinclude -o dynamic_main
- 使用:
LD_LIBRARY_PATH=mysharedlibfolder ./dynamic_main
GDB調試器
- 常用調試命令參數
開始調試:執行gdb [exefilename]
,進入gdb
調試程序,其中exefilename
為要調試的可執行文件名
## 以下命令后括號內為命令的簡化使用,比如run(r),直接輸入r就代表命令run$(gdb)help(h) # 查看命令幫助,如:help set$(gdb)run(r) # 重新開始運行(run-text:加載文本文件,run-bin:加載二進制文件),如果沒有加斷點,程序就直接運行結束了$(gdb)start # 單步執行,運行程序,停在第一行執行語句 $(gdb)list(l) # 查看源代碼(list-n,從第n行開始查看代碼。list+函數名:查看具體函數)$(gdb)set # 設置變量的值$(gdb)next(n) # 單步調試(逐過程,函數直接執行)$(gdb)step(s) # 單步調試(逐語句:跳入自定義函數內部執行)$(gdb)backtrace(bt) # 查看函數調用的棧幀和層級關系$(gdb)frame(f) # 切換函數的棧幀$(gdb)info(i) # 查看函數內部局部變量的數值$(gdb)finish # 結束當前函數,返回到函數調用點$(gdb)continue(c) # 繼續運行,相當于F5$(gdb)print(p) # 打印值及地址$(gdb)quit(q) # 退出gdb
$(gdb)break(b)+num # 在第num行設置斷點$(gdb)info breakpoints # 查看當前設置的所有斷點$(gdb)delete(d) breakpoints num # 刪除第num個斷點$(gdb)display # 追蹤查看具體變量值$(gdb)undisplay # 取消追蹤查看變量$(gdb)watch # 被設置觀察點的變量發生修改時,打印顯示$(gdb)i watch # 顯示觀察點$(gdb)enable breakpoints # 啟用斷點$(gdb)disable breakpoints # 禁用斷點$(gdb)x # 查看內存 x/20xw 顯示20個單元,16進制,每個單元4字節$(gdb)run argv[1] argv[2] # 調試時命令行傳參$(gdb)set follow-fork-mode child # Makefile項目管理:選擇跟蹤父子進程(fork())
Tips:
- 編譯時加上
-g
,才能用gdb
進行調試- 回車鍵:重復上一命令
- 調試流程
-
方法1
gdb myexe
b 13
run
- 調試會在第13行停住
-
方法2
gdb myexe
gdb myexe -p pid
- continue ?
- set args conf/gs_conf1.xml # 設置參數
- show args # 顯示參數
start
- 調試會停在第1行
-
方法3
- gdb --args test
- break main
- run
VSCode
- 安裝
直接在Ubuntu
軟件中心下載即可,因為vscode
在Ubuntu
中是首推軟件
- 工程(文件夾)
打開工程(文件夾)
- 控制臺進入工程目錄,然后輸入
code .
把當前目錄作為工程打開
關閉工程(文件夾)
File
->Close Folder
- 界面布局
- 菜單欄
File->Preferences
一些偏好設置View->Show Minimap
右側打開預覽縮略圖View->Editor Layout
分屏操作Go->Go to File...
打開搜索文件
面板Go->Go to Symbol in Workspace...
打開在工程搜索符號
面板Terminal->New Terminal
打開一個命令終端Terminal->Split Terminal
把打開的命令終端,再分一個屏出來- 點擊
垃圾箱按鈕
就可以把其中一個終端關閉
- 點擊
Help->Welcome
打開Welcome
界面,在Welcom
面板,你可以找到最近打開的工程
- 側邊欄
- Explorer
OPENEDITORS
展示當前打開了哪些文件XXX
打開的文件夾名字,以大寫字母形式展示OUTLINE
展示當前打開文件的大綱
,比如有哪些類,每個類有哪些成員TIMELINE
當你的倉庫是用git
來管理的時候,可以展示一些修改的記錄
- Search
- 在整個文件夾中整體查找
- Source Control
- 用
git
進行代碼管理 - 可以查看更改,丟棄更改
- 用
- Run and Debug
- Extensions
- 可以搜索插件
INSTALLED
已經安裝了哪些插件POPULAR
有哪些流行的插件RECOMMENDED
有哪些推薦的插件給你
- 編輯區
- 編輯代碼
- 狀態欄
- 光標當前所在行和列
- 空格是多少個字符
UTF8
編碼LF
行尾只有換行符,這是在Linux
環境下C++
表示你當前的編輯語言是C++
Linux
表示我們當前的系統是Linux
- 安裝插件
C/C++
Microsoft
出品CMake
twxs
出品CMake Tools
Microsoft
出品
- 快捷鍵
常用快捷鍵
ctrl+shift+p
打開命名
面板ctrl+p
打開搜索文件
面板- 直接輸入文件名,跳轉到文件
?
列出當前可執行的動作!
顯示Errors
或Warnings
,也可以ctrl+shift+m
:
跳轉到行數,也可以ctrl+g
直接進入@
跳轉到symbol
(搜索變量或者函數),也可以ctrl+shift+o
直接進入@:
根據分類跳轉到symbol
,查找變量或者函數,也可以ctrl+shift+o
后輸入:
進入#
根據名字查找symbol
,也可以ctrl+t
ctrl+t
打開在工程搜索符號
面板ctrl+反點
打開終端ctrl+b
關閉/打開 側邊欄ctrl+w
關閉當前文件alt+上下箭頭
當前行上下移動F2
變量統一重命名,類似于重構變量命名F12
轉到定義處
快捷鍵:編輯器與窗口管理
- 打開一個新窗口:
ctrl+shift+n
- 關閉窗口:
ctrl+shift+w
- 新建文件:
ctrl+n
- 切換出一個新的編輯器(最多
3
個):ctrl+\
(也可以按住ctrl
,然后點擊Explorer
里的文件名) - 左中右3個編輯器的快捷鍵:
ctrl+1
ctrl+2
ctrl+3
快捷鍵:代碼編輯相關
- 代碼格式化:
shift+alt+f
,或crtl+shift+p
后輸入format xxx
- 向上向下復制一行:
shift+alt+up
或shift+alt+down
- 列選擇:
shift+alt+鼠標選擇
快捷鍵:光標相關
- 定義處縮略圖:只看一眼而不跳轉過去
alt+f12
- 同時選中所有匹配:
ctrl+shift+l
快捷鍵:重構代碼
- 找到所有的引用:
shift+f12
- 跳轉到下一個
Error
或Warning
:當有多個錯誤時可按f8
逐個跳轉
快捷鍵:查找替換
- 查找:
ctrl+f
- 查找替換:
ctrl+h
- 整個文件夾中查找:
ctrl+shift+h
快捷鍵:顯示相關
- 全屏:
f11
- ZoomIn/ZommOut:
ctrl +/-
- 調試
launch.json
創建launch.json
- 點擊
Run and Debug圖標
,快捷鍵是ctrl+shift+d
- 點擊
creae a launch.json
超鏈接 - 點擊
C++(GDB/LLDB)
launch.json
生成在.vscode
目錄下
修改launch.json文件
- 修改
program
為${workspaceFolder}/build/mycmakeexe
- 加入
"preLaunchTask": "Build"
- 加入
"miDebuggerPath": "/usr/bin/gdb"
,如果gdb可以默認找到,就不需要配置
tasks.json
創建tasks.json
- 點擊
Terminal
- 點擊
Configure Default Build Task...
- 點擊
Create tasks.json file from template
- 點擊
Others
修改tasks.json
- 刪除自動生成的的
tasks.json
文件 - 輸入如下內容:
{"version": "2.0.0","options": {"cwd": "${workspaceFolder}/build"},"tasks": [{"type": "shell","label": "cmake","command": "cmake","args": [".."]},{"label": "make","group": {"kind": "build","isDefault": true},"command": "make","args": []},{"label": "Build","dependsOrder": "sequence","dependsOn": ["cmake","make"]}] }
- 集成Git
安裝Git
sudo apt update
sudo apt install git
git config --global user.name "xxx"
git config --global user.email "xxx@qq.com"
git config --list
檢查是否配置完成
CMake
- 語法特性介紹
- 基本語法格式:指令(參數1 參數2…)
- 參數使用
圓括弧
括起 - 參數之間使用
空格
或分號
分開
- 參數使用
- 指令是大小寫無關的,參數和變量是大小寫相關的
set(HELLO hello.cpp) add_executable(hello main.cpp hello.cpp) ADD_EXECUTABLE(hello main.cpp ${HELLO})
- **變量使用
${}
方式取值,但是在IF
控制語句是直接使用變量名
- 重要指令和常用變量
重要指令(大小寫無關)
cmake_minimum_required
-指定CMake
的最小版本要求- 語法:
cmake_minimum_required(VERSION versionNumber [FATAL_ERROR])
# CMake最小版本要求為3.0 cmake_minimum_required(VERSION 3.0)
- 語法:
project
-定義工程名稱,并可指定工程支持的語言- 語法:
project(projectname [CXX] [C] [Java])
# 指定工程為`HELLOWORLD` project(HELLOWORLD)
- 語法:
set
-顯式的定義變量- 語法:
set(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
# 定義SRC變量,其值為main.cpp hello.cpp set(SRC main.cpp hello.cpp)
- 語法:
include_directories
-向工程添加多個特定的頭文件搜索路徑- 相當于指定
g++
編譯器的-I
參數 - 語法:
include_directories[[AFTER|BEFORE] [SYSTEM] dir1 dir2...]
# 將/usr/include/myincludefolder 和 ./include 添加到頭文件搜索路徑 include_directories(/usr/include/myincludefolder ./include)
- 相當于指定
link_directories
-向工程添加多個特定的庫文件搜索路徑- 相當于指定g++編譯器的
-L
參數 - 語法:
link_directories(dir1 dir2...)
# 將/usr/lib/mylibfolder 和 ./lib 添加到庫文件搜索路徑 link_directories(/usr/lib/mylibfolder ./lib)
- 相當于指定g++編譯器的
add_library
-生成庫文件- 語法:
add_library(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN)
# 通過變量 SRC 生成 libhello.so 共享庫 add_library(hello SHARED ${SRC})
- 語法:
add_compile_options
-添加編譯參數- 語法:add_compile_options(…)
# 添加編譯參數 add_compile_options(-Wall -std=c++11 -O2)
- 語法:add_compile_options(…)
add_executable
-生成可執行文件- 語法:
add_executable(exename source1 source2...sourceN)
# 編譯main.cpp生成可執行文件 add_executable(main main.cpp)
- 語法:
target_link_libraries
-為target添加需要鏈接的共享庫- 等同于
g++
編譯器的-l
參數 - 語法:
target_link_libraries(target library1<debug|optimized> library2...)
# 將hello動態庫鏈接到可執行文件main target_link_library(main hello)
- 等同于
add_subdirectory
-向當前工程添加存放源文件的子目錄,并可以指定中間二進制和目標二進制存放的位置- 語法:
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
# 添加src子目錄,src中需有一個CMakeLists.txt add_subdirctory(src)
- 語法:
aux_source_directory
-發現一個目錄下所有的源代碼文件并將列表存儲在一個變量中,這個指令臨時被用來自動構建源文件列表- 語法:
aux_source_directory(dir VARIABLE)
# 定義SRC變量,其值為當前目錄下所有的源代碼文件 aux_source_directory(. SRC) # 編譯SRC變量所代表的源代碼文件,生成main可執行文件 add_executable(main ${SRC})
- 語法:
常用變量
CMAKE_C_FLAGS
gcc編譯選項CMAKE_CXX_FLAGS
g++編譯選項# 在CMAKE_CXX_FLAGS編譯選項后追加-std=c++11 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
CMAKE_BUILD_TYPE
編譯類型(Debug,Release)# 設定編譯類型為Debug,調試時需要選擇Debug set(CMAKE_BUILD_TYPE Debug) # 設定編譯類型為Release,發布時需要選擇Release set(CMAKE_BUILD_TYPE Release)
- 二進制目錄
CMAKE_BINARY_DIR
PROJECT_BINARY_DIR
<projectname>_BINARY_DIR
- 這三個變量指代的內容是一致的
- 如果是
in source build
,指的就是工程頂層目錄 - 如果是
out of source
編譯,指的是工程編譯發生的目錄 PROJECT_BINARY_DIR
跟其它兩個稍有區別,不過現在,你可以理解為他們是一致的
- 源代碼目錄
CMAKE_SOURCE_DIR
PROJECT_SOURCE_DIR
<projectname>_SOURCE_DIR
- 這三個變量指代的內容是一致的,不論采用何種編譯方式都是工程頂層目錄
- 也就是在
in source build
時,它跟CMAKE_BINARY_DIR等變量一致 PROJECT_SOURCE_DIR
跟其它兩個稍有區別,不過現在,你可以理解為他們是一致的
- CMAKE_C_COMPILER:指定C編譯器
- CMAKE_CXX_COMPILER:指定C++編譯器
- EXECUTABLE_OUTPUT_PATH:可執行文件輸出的存放路徑
- LIBRARY_OUTPUT_PATH:庫文件輸出的存放路徑
- CMake編譯工程
CMake
目錄結構:項目主目錄存放一個CMakeLists.txt
文件
兩種方式設置編譯規則:
- 包含源文件的子文件夾包含
CMakeLists.txt
文件,主目錄的CMakeLists.txt
通過add_subdirectory
添加子目錄即可 - 包含源文件的子文件夾未包含
CMakeLists.txt
文件,子目錄編譯規則體現在主目錄的CMakeLists.txt
中
編譯流程
在Linux平臺下使用CMake構建C/C++工程的流程如下:
- 手動編寫
CMakeLists.txt
- 執行命令
cmake PATH
生成Makefile
(PATH
是頂層CMakeLists.txt
所在的目錄) - 執行命令
make
進行編譯
兩種構建方式
-
內部構建(in-source build):不推薦使用
內部構建會在同級目錄下產生一大堆中間文件,這些中間文件并不是我們最終所需要的,和工程源文件放一起會顯得雜亂無章
## 內部構建# 在當前目錄下,編譯本目錄的CMakeLists.txt,生成Makefile和其他文件 cmake . # 執行make命令,生成target make
-
外部構建(in-source build):推薦使用
將編譯輸出文件與源文件放到不同的目錄中
## 外部構建# 1. 在當前目錄下,創建build文件夾 mkdir build # 2. 進入build文件夾 cd build # 3. 編譯上級目錄的CMakeLists.txt,生成Makefile和其它文件 cmake .. # 4. 執行make命令
- CMake示例
- 示例一
## 目錄結構:include/swap.h src/swap.cpp main.cpp build/# CMakeLists.txt cmake_minimum_required(VERSION 3.0) project(SWAP) include_directories(include) # 或者:include_directories(${CMAKE_SOURCE_DIR}/include) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O2 -Wall") # 或者:set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") # set(CMAKE_BUILD_TYPE Debug) add_executable(main_cmake main.cpp src/swap.cpp)# 執行 cd build cmake .. make ./main_cmake
安裝SSH
sudo apt-get install openssh-server
- 檢查有沒有啟動:
sudo ps -ef | grep ssh
- 如果沒有啟動:
sudo service ssh start
- 如果沒有啟動:
- 開機啟動ssh:
sudo systemctl enable ssh
xshell連接本地的wsl2
- xshell連接本地的wsl2
延申閱讀
- VSCode在Windows下的快捷鍵
- VSCode在Linux下的快捷鍵