今天本打算学习C++中的内存模型,以便于更加深入地了解程序的运行过程,但是在看书的过程中遇到了变量的链接性问题,本想写个程序试一试变量的链接性问题,结果发现不会写CMake,在网上查找CMake的资料后又发现了CMake和makefile这个是类似的,心想不如一起学了。然后在此总结一下。
简介:
一个C程序要想从代码变为可执行的文件,需要经过两个过程:编译
、链接
,一般我们在windows开发环境下使用Visual Studio,CLion等IDE(集成开发环境)时,编译器会自动执行这两步命令,无需经过复杂的操作,这也是IDE的方便之处。但是在linux开发环境下,如果想把一堆源文件链接在一起,组成一个可执行的文件,我们需要把每个文件的名字输入在命令行中,当我们每次修改源文件并且重新链接时这样做是非常麻烦的,因此有了makefile这个东西,将你所需要编译和链接的文件按照指定的格式写在一个makefile文件里,我的理解是makefile文件相当于一个脚本文件,只需要执行这个文件即可一键完成编译、链接的命令。这种文件在运行大型程序时是非常有用的。同样的还有CMake、Dockerfile类似的脚本文件,都是用来帮助我们更好地管理我们的程序。
基本格式:
目标:依赖
命令
注意:
- 命令前面要输入一个tab键
- 文件名要设置为makefile,如果没有设置为Makefile则在使用make命令执行该文件时要使用
make -f 文件名
的方式指定makefile的文件名
-
目标就是我们要生成的文件名,可以自行设置
-
依赖指的是生成这个目标程序需要依赖哪些文件
-
命令是指生成这个目标需要的命令,比如
g++ -o demo main.cpp printhello.cpp factorial.cpp
-
当依赖文件没有发生变化时再次执行make命令会提示当前已是最新,不需要更新
示例:
#这是一个示例
demo:main.cpp printhello.cpp factorial.cpp
g++ -o demo main.cpp printhello.cpp factorial.cpp
注意:
#在makefile作为注释符
// main.cpp
#include <iostream>
#include "functions.h"
using namespace std;
int main()
{
cout<<这是主函数<<endl;
printhello();
cout<<factorial<<endl;
}
//functions.h
#ifndef _FUNCTIONS_H_
#define _FUNCTIONS_H_
void printhello();
int factorial(int);
#endif
//printhello.cpp
void printhello()
{
cout<<"Hello World!"<<endl;
}
//factorial.cpp
int factorial(int n)
{
if(n==1)
{
return 1;
}
return n*factorial(n-1);
}
-
使用make命令即可按照makefile中的内容生成可执行程序
发现使用make命令后自动执行了我们刚才输入的命令,并且生成了一个名为hello的可执行文件
到这里发现使用makefile跟不用makefile好像也没啥太大的区别,但是此时注意一个问题,如果修改了部分源码再用make命令时,make命令还是会按照makefile中的命令全部编译一遍,达不到我们想要的只编译修改过的文件的效果
#版本2
TARGET = demo
OBJ = main.o printhello.o factorial.o
CXX = g++
$(TARGET):$(OBJ)
$(CXX) -o $(TARGET) $(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
这样即可只编译修改过的文件了
#版本3
CXX = g++
TARGET = hello
OBJ = main.o printhello.o factorial.o
CXXFLAGS = -c -Wall
$(TARGET):$(OBJ)
$(CXX) -o $@ $^
%.o:%.cpp
$(CXX) $(CXXFLAGS) $< -o $@
.PHONY:clean
clean:
rm -f *.o $(TARGET)
#版本4
CXX = g++
TARGET = hello
SRC = $(whildcard *.cpp)
OBJ = $(patsubst %.cpp,%.o,$(SRC))
CXXFLAGS = -c -Wall
$(TARGET):$(OBJ)
$(CXX) -o $@ $^
%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $@
.PHONY:clean
clean:
rm -f *.o $(TARGET)
CMake
CMake的作用是帮助我们在不同的系统环境下生成适应不同系统的makefile文件
CMake脚本的文件名:CMakeList
cmake_minimum_required(VERSION 3.10) #最小支持cmake的3.10版本
#设置project的名字为demo,版本设置为1.0,可以不设置
project(demo VERSION 1.0)
# 设置编译器的版本
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
add_executable(demo main.cpp printhello.cpp factorial.cpp) #demo是目标,后面的是依赖
使用CMake
cmake . #在当前目录下找CMakeList.txt并读取它,然后根据系统生成makefile文件然后使用make命令即可生成可执行程序
make
建议使用方法:在目录下建一个build文件夹,进入build文件夹内使用cmake ..
命令在build文件夹内生成makefile即可使工程目录不那么混乱
先简单地了解到这里吧,CMake使用这四条基本命令已经够用了,深入了解使用cmake可以看这一篇CMake