如图加入一些代码。(键盘输入=G修正缩进。:wq保存退出。)
编译、运行
g++ -Wall dp.C -std=c++17 -I/opt/root/include -L/opt/root/lib -lCore -lRIO -lTree -o dp
# 或者 g++ -Wall dp.C $(root-config --cflags) $(root-config --libs) -o dp
./dp
常用编译选项
-Wall : '输出所有编译警告'
-std=<c++xx> : '选择C++标准的版本'
-I<Path> : '添加头文件搜索路径(#include 中的文件)'
-L<Path> : '添加库文件搜索路径(.so二进制文件)'
-l<Name> : '链接libName.so库'
-o <File> : '指定输出文件'
-g : '添加调试符号'
-O<x> : '0 = 无优化, 1-2 = 优化, 3 = 高优化(更大的二进制文件), g = 为调试优化'
-E/-S/-c : '停止在预处理/编译/汇编'
C++编译流程
预处理 : 'cpp / g++ -E
处理 # 开头的指令(macro, include),进行了宏替换、头文件展开。'
编译、汇编 : 'g++ -S, g++ -c
编译:把C++代码成汇编代码。汇编:产生二进制的机器代码。'
链接 : 'ld / g++
把多个二进制文件合成库、可执行文件。'
可执行与可链接格式
ELF头 :'它包含了关于整个文件的基本信息,
比如文件是可执行文件、共享库还是目标文件,
以及它的架构类型(比如是32位还是64位)。'
程序头表 :'内存段信息,
告诉操作系统如何将程序加载到内存中。'
.text :'可执行指令,只读。'
.rodata :'只读数据,比如字符串常量和其他常量数据。'
.data :'可读写的数据,比如全局变量和静态变量。'
节头表 :'重定位需要的数据,在链接时使用,
在程序运行时通常不是必需的。'
程序的内存模型 (little-endian)
High Addresses ---> .----------------------.
| Environment |
|----------------------|
| | Functions and variable are declared
| STACK | on the stack.
base pointer -> | - - - - - - - - - - -|
| | |
| v |
: :
. . The stack grows down into unused space
. Empty . while the heap grows up.
. .
. . (other memory maps do occur here, such
. . as dynamic libraries, and different memory
: : allocate)
| ^ |
| | |
brk point -> | - - - - - - - - - - -| Dynamic memory is declared on the heap
| HEAP |
| |
|----------------------|
| BSS | Uninitialized data (BSS)
|----------------------|
| Data | Initialized data (DS)
|----------------------|
| Text | Binary code
Low Addresses ----> '----------------------'
能不能更智能地编译软件?
CMake - 跨平台的软件构建、测试、打包自动化系统
打开CLion,打开Project:
2024-winter-software-tutorial/playground
设置CMake Toolchain、生成CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(playground)
set(CMAKE_CXX_STANDARD 17)
find_package(ROOT REQUIRED)
include_directories(${ROOT_INCLUDE_DIRS}) # -I
link_directories(${ROOT_LIBRARY_DIR}) # -L
link_libraries(${ROOT_LIBRARIES}) # -l
message(STATUS "ROOT include dir: " ${ROOT_INCLUDE_DIRS})
message(STATUS "ROOT lib dir: " ${ROOT_LIBRARY_DIR})
include_directories(.)
add_executable(dp dp.C)
然后 Reset Cache and Reload Project、指定Working directory、
编译运行
mkdir build
cd build
# 目录树类似:
'├── build
└── source
├── CMakeLists.txt
├── include
└── src '
cmake ../source # cmake -D<选项> <含有CMake project的路径>
make -j$(nproc) # 使用nproc个cpu编译
# 或
cmake -DCMAKE_INSTALL_PREFIX=../install ../source
make install -j$(nproc) # 使用nproc个cpu编译
现有一个Project CutTool,包含一个可执行文件和一个共享函数库,能被其他项目调用。
# 从playground目录开始
docker run -ti --rm -v ${PWD}:/tmp/playground -w /tmp/playground \
ykrsama/darkshine-simulation bash --login
cd cuttool
# 编译
mkdir build && cd build
cmake ../
make
# ls 可以看到make输出了cutTool.exe libCutTool.so
# 运行
./cutTool.exe
阅读源码,在Project playground里调用CutTool。
在playground的CMakeLists里插入
find_package(CutTool REQUIRED PATHS cuttool/build)
include_directories(${CutTool_INCLUDE_DIRS})
link_directories(${CutTool_LIBRARY_DIRS})
link_libraries(${CutTool_LIBRARIES})
message(STATUS "CutTool include dir: " ${CutTool_INCLUDE_DIRS})
message(STATUS "CutTool lib dir: " ${CutTool_LIBRARY_DIRS})
在dp::Loop里调用passCut函数