Makefile编译和链接

一、编译和链接

一个C/C++文件要经过预处理(preprocessing)、编译(compilation)、汇编(assembly)和链接(linking)等4步才能变成可执行文件。在日常交流中通常使用“编译”统称这4个步骤。

1、预编译(预处理)

在集成开发环境中,编译,链接是同时完成的。其实,C语言编译器在对源代码编译之前,还需要进一步的处理:预编译。所以,完整的步骤是:预编译 -> 编译 -> 链接。

预编译的主要作用如下:

  • 将源文件中以“#include”格式包含的文件复制到编译的源文件中。
  • 用实际值替换用“#define”定义的字符串。
  • #if,#ifdef,#ifndef,#elif,#else和#endif指令编译器可以根据测试的条件来将一段文本包含到程序中或排除在程序之外。

C/C++源文件中,以“#”开头的命令被称为预处理命令,如包含命令“#include”、宏定义命令“#define”、条件编译命令“#if”、“#ifdef”等。预处理就是将要包含的头文件插入源文件中;将宏定义展开;根据条件编译命令选择要使用的代码。

使用条件编译,可方便地处理程序的调试版本和正式版本,也可使用条件编译使程序的移植更方便

#if 的使用格式如下:

#if 常量表达式
   程序段
#else
  程序段
#endif

若常量表达式的值为真(非0),则对程序段1进行编译,否则对程序段2进行编译。因此可以使程序在不同条件下完成不同的功能。

2、编译

源程序(用源语言写的,一段C++代码,自己能看懂,计算机看不懂)转化为目标程序的中间文件(机器语言程序,计算机可以理解)的操作。

C语言的编译器有很多种,不同的平台下有不同的编译器,例如:

  • Windows 下常用的是微软开发的 Visual C++,它被集成在 Visual Studio 中,一般不单独使用;目标文件后缀.obj
  • Linux 下常用的是 GUN 组织开发的GCC,很多 Linux 发行版都自带 GCC;目标文件后缀.o
  • Mac 下常用的是 LLVM/Clang,它被集成在 Xcode 中(Xcode 以前集成的是 GCC,后来由于 GCC 的不配合才改为 LLVM/Clang,LLVM/Clang 的性能比 GCC 更加强大)。
gcc hello.c -c -o hello.o

3、链接

链接就是一个“打包”的过程,它将所有的目标文件以及系统组件组合成一个可执行文件

C语言代码经过编译以后,会变成了二进制形式的目标文件(Object File)--- 对于 Visual C++,目标文件的后缀是.obj,对于 GCC,目标文件的后缀是.o。但此时的代码还不能运行起来。因为它还需要和系统提供的组件(比如标准库)结合起来,这些组件都是程序运行所必须的。例如我们要在屏幕中输出字符,这必须调用系统提供的库才能够实现。

(1)创建静态库

ar rcs hello.a hello.o

(2)创建可执行目标文件

gcc -o hello hello.o

二、Makefile脚本的撰写

-o:指定输出文件名为file,这个名称不能跟源文件名同名  
-E:只预处理,不会编译、汇编、链接
-S:只编译,不会汇编、链接
-c:只编译和汇编,不会链接

makefile是用于自动编译和链接的,一个工程有很多文件组成,每一个文件的改变都会导致工程的重新链接。但是不是所有的文件都需要重新编译,makefile能够纪录文件的信息,决定在链接的时候需要重新编译哪些文件!

一个典型的规则的语法为:

目标: 预置条件
步骤

目标并不要求是一个文件,也可以只是步骤的名字,就如我们的例子中一样。我们称之为“伪目标”。

# CROSS_COMPILE = arm-hisiv300-linux-
CC = emcc
AR = emar

IFLAG = -I../../include\
-I../../C2JS/C2JS\

CFLAGS 	= $(IFLAG) -Wall -D__WEBJS__ -DSUPPORT_OPENGL -DSUPPORT_OPENAL -O3 
#-fsanitize=address

LDFLAGS = -s "EXPORTED_RUNTIME_METHODS=['ccall', 'getValue','writeArrayToMemory','print','UTF8ToString']" -s USE_PTHREADS=1 -s INITIAL_MEMORY=500MB -s MAXIMUM_MEMORY=1000MB -s ALLOW_MEMORY_GROWTH=1 -s MAX_WEBGL_VERSION=2 -s USE_FREETYPE=1 -lopenal -s PTHREAD_POOL_SIZE_STRICT=0 -s GL_PREINITIALIZED_CONTEXT=1 --js-library renderer.js -s OFFSCREENCANVAS_SUPPORT=1 -s ENVIRONMENT=web,worker -s EXPORT_NAME='JSPlayerModule' -s MODULARIZE=1 --embed-file LucidaBrightDemiBold.ttf
#-msimd128 -msse4.2 --preload-file simsun.ttc --embed-file LucidaBrightDemiBold.ttf -s WEBGL2_BACKWARDS_COMPATIBILITY_EMULATION=1 -s INITIAL_MEMORY=100MB -s MAXIMUM_MEMORY=1000MB -fexceptions  

EXCLUDE_SRCS += ../../playctrl/hello.cpp
EXCLUDE_SRCS += ../../src/main.cpp

SRCS =$(wildcard ../../C2JS/C2JS/*.cpp)\
$(wildcard ../../src/ManageModule/*.cpp)\


SOURCES = $(filter-out $(EXCLUDE_SRCS),$(SRCS))

LIBS = $(wildcard ./lib/web/*.a)
	   	
#OBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))
OBJS = $(patsubst %.cpp,%.o,$(SOURCES))

TARGET = Decoder.js
OBJ_TARGET = STPlayer.a

	
all: $(OBJS) $(OBJ_TARGET)

#all: $(TARGET)

$(OBJ_TARGET): $(OBJS)
	$(AR) rcs $(OBJ_TARGET) $(notdir $(OBJS))

$(TARGET):	
	$(CC) -O3 --bind $(OBJ_TARGET) $(LIBS) -o $(TARGET) $(LDFLAGS) $(CFLAGS)

#--memoryprofiler -O3 --profiling -fsanitize=address
	
.cpp.o:
	$(CC) $(CFLAGS) -c $<

clean:
	rm -f *.o *.a Decoder.worker.js $(OBJS) $(OBJ_TARGET) $(TARGET)
	rm -rf $(DIR)

你可能感兴趣的:(编译器,gnu,服务器)