C++ 环境准备

sudo apt-get install g++ 安装编译器。
sudo apt-get install gdb 安装调试器。
在 vscode 中安装拓展

编译指令

简单:”g++ 选项 源文件名”,例如 g++ -o test main.cpp
高级:”g++ 选项 源文件名 输出选项 链接库”,例如 g++ -std=c++17 -Wall -O2 -I./include main.cpp -o my_app -L./lib -lpthread

  1. 编译选项
    -std=c++17 指定 C++ 标准。
    -I./include 指定头文件搜索路径。
    -g 调试, Wall 警告。
    -On 编译、链接时优化,提高可执行程序运行速度,减慢编译速度,默认 -O0, 推荐 -O2
    -c 只编译不链接,常用于把源文件编译成静态库或动态库。

  2. 输出选项
    -o 文件名 指定输出文件名。

  3. 链接库
    -L./libs 指定库文件搜索路径。
    -l库文件名 链接库,若库文件名为 libpthread.so 则命令为 -lpthread

静态库和动态库

若动态库和静态库同时存在,编译器将优先使用动态库。

概念与特点

静态库:程序在编译时把库文件的二进制代码链接到目标程序中,这种方式称为静态链接。
如果多个程序中用到了同一静态库中的函数或类,就会存在多份拷贝

  • 静态库的链接在编译时期完成,执行时代码加载速度快。
  • 目标程序的可执行文件较大,浪费空间。
  • 程序的更新和发布不方便,一个静态库更新后,所有使用它的程序都需要重新编译。

动态库:程序在运行时把库文件的二进制代码载入。
如果多个进程中用到了同一动态库中的函数或类,内存中只会存在一份,避免了空间浪费问题

  • 可实现进程间的代码共享,因此动态库也称为共享库。
  • 程序升级较简单,无需重新编译程序,只需更新动态库即可。
  • 需要提前设置 LD_LIBRARY_PATH 环境变量。

制作

  1. 制作静态库
    1.”g++ -c 源代码文件清单”,如 g++ -c source1.cpp source2.cpp source3.cpp
    2.”ar rcs lib库名.a 目标文件清单”,如 ar rcs libmylib.a source1.o source2.o source3.o

  2. 制作动态库
    “g++ -fPIC -shared 源代码文件清单 -o lib库名.so”,如 g++ -fPIC -shared math.cpp -o libmymath.so

Makefile 与 CMake

Makefile

  1. 在目录下创建文件 “Makefile” ,编写命令内容。开头需要使用 Tab 缩进,而非空格
  2. 运行命令 make 即可编译链接出可执行程序,使用 “./程序名” 运行。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    # # v1
    # test: main.cpp printhello.cpp factorial.cpp
    # g++ -o test main.cpp printhello.cpp factorial.cpp

    # # v2
    # CXX = g++
    # TARGET = test
    # OBJ = main.o printhello.o factorial.o
    # # make 时执行 g++, 先找 TARGET , TARGET 不存在找 OBJ, OBJ 不存在,编译三个 .cpp 文件生成 .o 文件
    # # 然后再链接 OBJ 文件,生成可执行文件 hello
    # $(TARGET): $(OBJ)
    # $(CXX) -o $(TARGET) $(OBJ)
    # # 编译 OBJ
    # main.o: main.cpp
    # $(CXX) -c main.cpp
    # printhello.o: printhello.cpp
    # $(CXX) -c printhello.cpp
    # factorial.o: factorial.cpp
    # $(CXX) -c factorial.cpp

    # v3
    CXX = g++
    TARGET = hello
    OBJ = main.o printhello.o factorial.o
    # 编译选项,显示所有的warning
    CXXFLAGS = -c -Wall
    # $@表示的就是冒号前面的TARGET,$^表示的是冒号后OBJ的全部.o依赖文件
    $(TARGET): $(OBJ)
    $(CXX) -o $@ $^
    # $<表示指向%.cpp依赖的第一个,但是这里依赖只有一个
    # $@表示指向%.o
    %.o: %.cpp
    $(CXX) $(CXXFLAGS) $< -o $@
    # 为了防止文件夹中存在一个文件叫clean
    .PHONY: clean
    # -f表示强制删除,此处表示删除所有的.o文件和TARGET文件
    clean:
    rm -f *.o $(TARGET)

CMake

  1. 在项目根目录下创建 .txt文件 CMakeLists.txt ,编写内容。
  2. 创建 “build” 文件夹 mkdir build ,进入该目录 cd build
  3. 运行命令 cmake .. ,执行根目录的内容,在当前目录生成 “Makefile”。
  4. 运行命令 make 即可编译链接出可执行程序,使用 “./程序名” 运行。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    cmake_minimum_required(VERSION 3.10)

    project(test)

    set(CMAKE_CXX_STANDARD 20) # 指定 C++ 标准

    add_executable(test main.cpp factorial.cpp printhello.cpp)

    ## 自动查找当前目录下所有的源文件,并将列表赋值给变量 SRC_LIST
    #aux_source_directory(. SRC_LIST)

    ## 使用变量 SRC_LIST 编译程序,不用手写 main.cpp factorial.cpp ...
    #add_executable(test ${SRC_LIST})