UNIX下make命令、gcc命令以及makefile怎么写
0.一个程序的编译过程:
0.1 gcc(-E、-S、-o)

预处理:就是将.c转为.i,将.c中需要调用的头文件包含进来,比如会出现调用的函数的声明部分,替换#define的宏常量和宏代码段,去掉注释,预处理阶段不检查语法错误
gcc -E Demo.c-o Demo.i
编译:将.i文件中源码转化为汇编代码.s文件,编译肯定会检查语法错误
gcc -S Demo.i -o Demo.s
汇编: 将.s文件中的汇编源码转化未机器能执行的二进制机器码,生成目标文件.o
gcc -c Demo.s -o Demo.o
链接:要把函数库中的函数定义给关联进来
gcc Demo.o -o Demo
0.2 gcc生成.a文件
在Linux中,静态库的另一个名字叫归档文件(archive),管理这种归档文件的工具叫 ar
例子:
在头文件 say.h包含函数 sayHello()的原型和类 Say 的定义:
/* say.h */
#include <iostream>
extern void sayhello(void);
class Say {
private:
char *string;
public:
Say(char *str)
{
string = str;
}
void sayThis(const char *str)
{
std::cout << str << " from a static library\n";
}
void sayString(void);
};
say.cpp是要加入到静态库中的两个对象文件之一的源码。它包含 Say 类中 sayString()函数的定义体;类 Say 的一个实例 librarysay的声明也包含在内:
/* say.cpp */
#include "say.h"
void Say::sayString()
{
std::cout << string << "\n";
}
Say librarysay("Library instance of Say");
源码文件 syshello.cpp 是我们要加入到静态库中的第二个对象文件的源码。它包含函数 sayhello() 的定义:
/* sayhello.cpp */
#include "say.h"
void sayhello()
{
std::cout << "hello from a static library\n";
}
编译成静态库文件:
$ g++ -c sayhello.cpp
$ g++ -c say.cpp
$ ar -r libsay.a sayhello.o say.o // ar 配合参数 -r 创建一个新库 libsay.a
主程序saymain.cpp调用该静态库:
/* saymain.cpp */
#include "say.h"
int main(int argc,char *argv[])
{
extern Say librarysay; //表明这个对象在其他模块中已经定义过了
Say localsay = Say("Local instance of Say");
sayhello();
librarysay.sayThis("howdy");
librarysay.sayString();
localsay.sayString();
return(0);
}
编译和链接:
$ g++ saymain.cpp libsay.a -o saymain
执行saymain,生成:
hello from a static library
howdy from a static library
Library instance of Say
Local instance of Say
1.关于makefile:
makefile文件类似一个脚本,用于执行Linux端工程文件的编译操作
make工具的三部分:
a. 明确编译的目标
b. 目标的依赖内容
c. 执行怎样的操作
例子:a依赖b,执行cmdbtoa操作(注意使用tab分隔要运行的指令操作)
a:b
cmdbtoa
2.makefile具体怎么写:
准备两个.cpp一个.h
text1.cpp
#include<stdio.h>
#include "test2.h"
int main()
{
printf("This is test1!\n");
PrintTest2();
return 0;
}
test2.cpp
#include<stdio.h>
#include "test2.h"
void PrintTest2()
{
printf("This is test2!\n");
}
text2.h
#ifndef TEST2_H_
#define TEST2_H_
void PrintTest2();
#endif
接着写一个Makefile文件:
test: test1.o test2.o //test依赖目标文件test1.o、test2.o
gcc -Wall test1.o test2.o -o test //编译链接test1.o、test2.o,修改生成的exe文件名为test
test1.o: test1.c test2.h
gcc -c -Wall test1.c -o test1.o //仅执行编译test1.c不链接,修改生成目标文件名为test1.o
test2.o: test2.c test2.h
gcc -c -Wall test2.c -o test2.o
clean:
rm -rf *.o test //删除掉所有.o以及可执行文件,make clean执行
解释一下:
-Wall:输出所有警告信息。
-c: 只编译不链接,所以只生成目标文件.0
-o:表示指定编译后可执行文件的名称,-o后加exe文件名,不加gcc就给出预设的可执行文件a.out
-S:只激活预处理和编译,就是指把文件编译成为汇编代码。
-E: 预处理生成.i)
gcc -c hello.c 编译生成hello.o文件
gcc -o hello hello.c 生成可执行文件hello
3.makefile中使用变量($符调用):
OBJS = test1.o test2.o
G = gcc
CFLAGS = -Wall -O -g
test:$(OBJS)
$(G) $(OBJS) -o test
test1.o:test1.c test2.h
$(G) $(CFLAGS) -c test1.c
test2.o:test2.c test2.h
$(G) $(CFLAGS) -c test2.c
clean:
rm -rf *.o test
解释一下:
变量的格式是“变量名= 内容”;若要引用这个变量,只需要用:$(变量名)
-O:在编译时进行优化。
-g:表示编译debug版本
4.makefile中使用函数:
C = gcc
G = g++
CFLAGS = -Wall -O -g
TARGET = ./test
%.o:%.c
$(C) $(CFLAGS) -c $< -o $@
%.o:%.cpp
$(G) $(CFLAGS) -c $< -o $@
SOURCES = $(wildcard *.c *.cpp)
OBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))
$(TARGET):$(OBJS)
$(G) $(OBJS) -o $(TARGET)
chmod a+x $(TARGET)
clean:
rm -rf *.o test
本文来自博客园,作者:{author 周小鱼},转载请注明原文链接:https://www.cnblogs.com/zhouxiaoyu16/p/16071652.html

浙公网安备 33010602011771号