Makefile编写及一个简单的Makefile架构实现

时间:2022-01-04 09:25:07

本文通过总结makefile的相关使用,并将以前大型项目中用到的Makefile简单的记录下,以便以后快速应用:

  • Makefile常用命令
  • GCC/G++常用编译参数
  • 简单Makefile框架实现

Makefile常用命令

make Makefile/makefile/GNUMakefile
当Makefile名字不是上述三个名字时,需要加-f 去编译,如xxx.mk文件,需使用make -f xxx.mk 去编译;

GCC/G++常用编译参数

  • -shared
    Produce a shared object which can then be linked with other objects to for man executable. Not all systems support this option.
  • -D_REENTRANT
    在一个多线程程序里,默认情况下,只有一个errno变量供所有的线程共享。在一个线程准备获取刚才的错误代码时,该变量很容易被另一个线程中的函数调用所改变。类似的问题还存在于fputs之类的函数中,这些函数通常用一个单独的全局性区域来缓存输出数据。
    为解决这个问题,需要使用可重入的例程。可重入代码可以被多次调用而仍然工作正常。编写的多线程程序,通过定义宏_REENTRANT来告诉编译器我们需要可重入功能,这个宏的定义必须出现于程序中的任何#include语句之前。
    _REENTRANT为我们做三件事情,并且做的非常优雅:
    (1)它会对部分函数重新定义它们的可安全重入的版本,这些函数名字一般不会发生改变,只是会在函数名后面添加_r字符串,如函数名gethostbyname变成gethostbyname_r。
    (2)stdio.h中原来以宏的形式实现的一些函数将变成可安全重入函数。
  • Makefile三个非常有用的变量
    分别是 @ ^, < $ @ $ $ <–第一个依赖文件。
  • -w -W和-Wall选项
    -w的意思是关闭编译时的警告,也就是编译后不显示任何warning,因为有时在编译之后编译器会显示一些例如数据转换之类的警告,这些警告是我们平时可以忽略的。
    -Wall选项意思是编译后显示所有警告。
    -W选项类似-Wall,会显示警告,但是只显示编译器认为会出现错误的警告。

简单Makefile框架实现

此处将写三个makefile文件,它们为了大型项目的集成,将一个全要素的makefile文件拆分开来编写,然后通过include相关联;

Makefile代码框架

Makefile编写及一个简单的Makefile架构实现

MakeFileTemplate

#########################################################
###############Makefile Path公共变量定义#################
#########################################################
EB_SRC_PATH = $(JTTS_SRC_ROOT)/src/Product/Engine/jTTS_EB9
EB_SRC_COMMON=$(JTTS_SRC_ROOT)/src/Product/Engine/common
EB_RELEASE_PATH =$(JTTS_SRC_ROOT)/bin
EB_LIB_PATH=$(JTTS_SRC_ROOT)/libs
##########################################################
####GCC编译参数定义
##########################################################
CC :=g++
INCLUDE :=
LIBS :=
DEFS :=
CFLAGS := -g -w -O2 -rdynamic
SRC_FILES :=
INSTDIR :=
LIB_INC :=
###########################################################
# define gloab variable
###########################################################
TARGET = libjTTS_EB9.so
TARGET_COPY = libjTTS_EB9.so
MODULE_OUTPUT_PATH = $(EB_RELEASE_PATH)/$(TARGET_COPY)


INCLUDE +=-I$(EB_SRC_PATH) \
-I$(JTTS_SRC_ROOT)/src/Product/OSLayer/include \
-I$(EB_SRC_COMMON) \
-I$(EB_SRC_PATH) \
-I$(JTTS_SRC_ROOT)/src/Ext_SDK/Ext_SDK/EB/include \
-I$(JTTS_SRC_ROOT)/src/Common/include \
-I$(JTTS_SRC_ROOT)/src/Product/Common/include \
-I$(JTTS_SRC_ROOT)/src/Ext_SDK/Encrypt \
-I$(JTTS_SRC_ROOT)/depends/ACE_wrappers \
-I$(JTTS_SRC_ROOT)/depends


LIB_INC +=-L$(EB_LIB_PATH) \
-L$(EB_RELEASE_PATH) \
-L$(EB_SRC_PATH)



SRC_FILES += $(shell find $(EB_SRC_PATH) -name jTTS_EB.cpp)
SRC_FILES += $(shell find $(EB_SRC_PATH) -name ejTTSAgent.cpp)
SRC_FILES += $(shell find $(EB_SRC_PATH) -name ejTTSInstance.cpp)
SRC_FILES += $(shell find $(EB_SRC_PATH) -name Win_Linux_file_func.cpp)
SRC_FILES += $(shell find $(EB_SRC_COMMON) -name CQueue.cpp)
SRC_FILES += $(shell find $(EB_SRC_COMMON) -name backaudio.cpp)
SRC_FILES += $(shell find $(EB_SRC_COMMON) -name JIniFile.cpp)



LIBS += -lOSLayer \
-lACE \
-ljTTS_Audio \
-liconv \
libjtsecure_app.a \
libjtsecure_engine.a \
-lmkl_rt \
-lSmallFile \
-lz \
-lpthread \
-lrt \
-ldl

ALL:$(TARGET)
cp $(EB_SRC_PATH)/$(TARGET) $(EB_RELEASE_PATH)/$(TARGET_COPY) -f

%.o:%.cpp
$(CC) -fPIC -c $(SRC_FILES) $(INCLUDE)


OBJ_SRC=$(addprefix $(EB_SRC_PATH)/,$(notdir $(SRC_FILES:%.cpp=%.o)))

$(TARGET): $(OBJ_SRC)
$(CC) -shared -o $(TARGET) $(OBJ_SRC) ${LIBS} $(LIB_INC)

clean:
-rm -f $(TARGET)
-rm -f *.o

def.app.mak

##########################################################
#所有的编译用的makefile都必须引用该文件
###
#######################################################

include $(XS_ROOT)/build/common_mak/def_pub.mak
CC :=g++
INCLUDE :=
LIBS :=
DEFS :=
#ifeq ($(ATN_FLAG_WALL_DELETE),yes)
#CFLAGS := -Os
#else
CFLAGS := -O2
#endif
SRC_FILES :=
INSTDIR :=

###########################################################
# define gloab variable
###
########################################################

ifneq ($(PRODUCT_TYPE),PTN)
ENDIAN_DEFS := -DVOS_BYTE_ORDER=VOS_BIG_ENDIAN
endif

### public define ###
ifeq ($(CPU_INSX),x8664)
DEFS += -DVOS_OS_VER=4
DEFS += -DVOS_HARDWARE_PLATFORM=3
DEFS += -DVOS_CPU_TYPE=44
endif

ifeq ($(CPU_INSX),ARM64)
DEFS += -DVOS_OS_VER=4
DEFS += -DVOS_HARDWARE_PLATFORM=3
DEFS += -DVOS_CPU_TYPE=44
endif

INCLUDE += -I/usr/include

def_pub.mak

XS_ROOT=/home/heyongxin/xs_epoll
CPU_INSX=ARM64
PRODUCT_TYPE=PTN
SROUTER=0

exec_app.mak

CFLAGS += -D_REENTRANT -Wall -pedantic -Isrc -g
LIBS += -lpthread
all: $(TARGET)

clean:
rm -f $(TARGET) *~ */*~ */*.o

$(TARGET): $(SRC_FILES) $(XS_ROOT_INC_PATH)/*
$(CC) -fPIC ${CFLAGS} -o $@ $< $(INCLUDE) ${LIBS}

xs_epoll_build.mk

include $(XS_ROOT)/build/common_mak/def_pub.mak
include $(XS_ROOT)/build/common_mak/def_app.mak

XS_ROOT_SRC_PATH = $(XS_ROOT)
XS_ROOT_INC_PATH =$(XS_ROOT)/include
XSEPOLL_RELEASE_PATH =$(XS_ROOT)/bin


DEFS += -DAA_AA

ifeq ($(CPU_INSX),ptn)
CFLAGS += -DBYTEORDER_LITTE
else
CFLAGS += -DBYTEORDER_BIG
endif

MODULE = xs_epoll
TARGET = $(XSEPOLL_RELEASE_PATH)/$(MODULE)
MODULE_OUTPUT_PATH = $(XSEPOLL_RELEASE_PATH)/$(MODULE)
TARGET_COPY = lxs_epoll.so


SRC_FILES += $(shell find $(XS_ROOT_SRC_PATH)/src -name xs_epoll.c)
#SRC_FILES += $(shell find $(XS_ROOT_SRC_PATH)/src -name xs_epoll.c)
#SRC_FILES += $(shell find $(XS_ROOT_SRC_PATH)/src -name xs_epoll.c)

ifeq ($(SROUTER),1)
LIBS += -lsfeaa
DEFS += -DCPU_INSA_X86
endif

ifdef UT_FILES
CC += -O2
endif

INCLUDE += -I$(XS_ROOT)/include
# -I$(XS_ROOT)/product/xframe/aa/include \
# -I$(XS_ROOT)/product/xframe/aa/include \
# -I$(XS_ROOT)/product/aa/include \

include $(XS_ROOT)/build/common_mak/exec_app.mak

build.sh

#!/bin/bash
# testing the script
export XS_ROOT="/home/heyongxin/xs_epoll"
#./build.sh build xs_epoll all clean

function Main_Build_Entrance {
echo $1
echo $2
echo $3
echo $4
if [[ $4 -eq "clean" ]]
then
make -f ./xs_epoll_build.mk clean
make -f ./xs_epoll_build.mk
elif [ $4 -eq "gdb" ] && [ $1 -eq "run" ]
then
gdb $(XS_ROOT)/bin/xs_epoll
else
make -f ./xs_epoll_build.mk
fi
}

Main_Build_Entrance $1 $2 $3 $4
#make -f ./xs_epoll_build.mk

xs_epoll.h

#ifndef _XS_EPOLL_H
#define _XS_EPOLL_H
#include <pthread.h>
#include <stdint.h>
#include <sys/resource.h>
#define xs_defult_thread_size 10
#define EPOLL_DEFAULT_SIZE 10
#define BUFFER_SIZE 1024
#define EXIT_ERROR -1
#define EXIT_OK 0
typedef void(* XS_PFUN)(void* );
typedef pthread_t xs_pthread_t;
typedef pthread_cond_t xs_pthread_cond_t;
typedef pthread_mutex_t xs_pthread_mutex_t;
typedef pthread_attr_t xs_pthread_attr_t;
typedef int XSOCKET;
typedef struct epoll_event xs_epoll_event;


typedef struct block_queue
{
#ifdef __VECTOR__
vector queue;
#else
int queue[xs_defult_thread_size];
long size;
#endif
xs_pthread_cond_t cond;
xs_pthread_mutex_t mutex;
}block_queue_t;

block_queue_t *bq;

typedef struct block_queue_param
{
void* func;
void* queue; /* Point to block queue structure */
}block_queue_param_t;

block_queue_param_t bqp;

int g_xs_thread_count = xs_defult_thread_size;
int g_epoll_fd = -1;

xs_epoll_event xs_ev, xs_events[EPOLL_DEFAULT_SIZE];
int g_epoll_size = EPOLL_DEFAULT_SIZE;
int g_serv_fd = -1;
void * xs_malloc(int size);
void xs_free(void *ptr);
int xs_release_socket(XSOCKET socket);
int xs_net_recv( XSOCKET s, char *buf, int len);
int xs_net_send( XSOCKET s,char *buf,int len);
int xs_close_socket(int fd);
int xs_init_server(const char *name,short int port);

#endif

xs_epoll.c

#include <assert.h>
#include <sys/epoll.h> /* epoll head file*/
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <memory.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "xs_epoll.h" /* epoll releated include file */



void * xs_malloc(int size)
{
return malloc(size);
}
void xs_free(void *ptr)
{
return free(ptr);
}

void xs_dump_error_str(int errno)
{
char * pmsg = strerror(errno);
printf("ErrorMsg:%s\n",pmsg);
}
int xs_release_socket(XSOCKET socket)
{

}
void xs_pthread_cond_init(pthread_cond_t* cond,void* value)
{
*cond=PTHREAD_COND_INITIALIZER;
}
void xs_pthread_mutex_init(pthread_mutex_t* mutex,void* value)
{
*mutex=PTHREAD_MUTEX_INITIALIZER;
}

int xs_net_recv( XSOCKET s, char *buf, int len)
{
return recv(s, buf, len, 0);
}
int xs_net_send( XSOCKET s,char *buf,int len)
{
return send(s,buf,len,0);
}

int xs_pthread_mutex_lock(xs_pthread_mutex_t *mutex)
{
return pthread_mutex_lock(mutex);
}
int xs_pthread_cond_wait(xs_pthread_cond_t *cond, xs_pthread_mutex_t *mutex)
{
return pthread_cond_wait(cond,mutex);
}
int xs_pthread_mutex_unlock(xs_pthread_mutex_t *mutex)
{
return pthread_mutex_unlock(mutex);
}
int xs_pthread_attr_init(pthread_attr_t *attr)
{
return pthread_attr_init(attr);
}
int xs_create_server(const char* name,short int port)
{
return 1;
}
int xs_pthread_cond_signal(xs_pthread_cond_t *cond)
{
return pthread_cond_signal(cond);
}

XSOCKET xs_net_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
return accept(sockfd,addr,addrlen);
}
int xs_pthread_cond_destroy(xs_pthread_cond_t *cond)
{
return pthread_cond_destroy(cond);
}

int xs_pthread_mutex_destroy(xs_pthread_mutex_t *mutex)
{
return pthread_mutex_destroy(mutex);
}
int xs_close_socket(int fd)
{
return close(fd);
}

void set_nonblocking(int sock)
{

int flags;
flags = fcntl(sock, F_GETFL, 0);
if (flags < 0) {

perror("fcntl(F_GETFL) failed");
exit(EXIT_ERROR);
}

if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) {

perror("fcntl(F_SETFL) failed");
exit(EXIT_ERROR);
}
}


/* create an epoll 实例 */
int xs_epoll_create(int __c)
{
XSOCKET __efd__ = -1;

__efd__ = epoll_create(__c);
if(__efd__ < 0)
{
//xs_dump_error_str(errno);
return EXIT_ERROR;
}

return (__efd__);
}

int xs_epoll_ctl(XSOCKET __efd, int __method, XSOCKET __fd, struct epoll_event* __p)
{
int __result__ = -1;

__result__ = (epoll_ctl(__efd, __method, __fd, __p) < 0);
if(__result__ < 0)
{
//xs_dump_error_str(*errno);
return EXIT_ERROR;
}

return EXIT_OK;
}
int xs_epoll_wait(XSOCKET __efd, struct epoll_event* __ev, int __c,int __tw)
{
int __num__ = -1;

__num__ = epoll_wait(__efd, __ev, __c, __tw);
if(__num__ < 0)
__num__ = EXIT_ERROR;

return (__num__);
}

int xs_epoll_close(XSOCKET __f)
{
return xs_release_socket(__f);
}

/*
Add fd to epoll fd Register
the target file descriptor fd on the epoll instance referred to by the file descriptor epfd and
associate the event with the internal file linked to fd.
*/

int xs_epoll_add(int __epollfd,int __fd,int __mod)
{
xs_epoll_event __xs_ev__;

__xs_ev__.events = __mod;
__xs_ev__.data.fd = __fd;

if(xs_epoll_ctl(__epollfd, EPOLL_CTL_ADD, __fd, &__xs_ev__) < 0)
return EXIT_ERROR;

return EXIT_OK;
}

/*
Remove (deregister) the target file descriptor fd from the epoll instance referred to by epollfd.
The event is ignored and can be NULL.
In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required a non-NULL pointer in event
Since Linux 2.6.9, event can be specified as NULL when using EPOLL_CTL_DEL.
*/

int xs_epoll_del(int __epollfd,int __fd)
{
xs_epoll_event __xs_ev__;

/* We should better set event not NULL */
__xs_ev__.events = __xs_ev__.events;
__xs_ev__.data.fd = __fd;

if(xs_epoll_ctl(__epollfd, EPOLL_CTL_DEL, __fd, &__xs_ev__) < 0)
return EXIT_ERROR;

return EXIT_OK;
}


/* Change the event associated with the target file descriptor __fd. */
int xs_epoll_mode(int __epollfd,int __fd,int __newmod)
{
xs_epoll_event __xs_ev__;

__xs_ev__.events = __newmod;
__xs_ev__.data.fd = __fd;

if(xs_epoll_ctl(__epollfd, EPOLL_CTL_MOD, __fd, &__xs_ev__) < 0)
return EXIT_ERROR;

return EXIT_OK;
}

/*
xs_epoll_init: creates an epoll "instance", requesting the kernel to allocate an event
backing store dimensioned for size descriptors.
Since Linux 2.6.8, the size argument is unused, but must be greater than zero.
(The kernel dynamically sizes the required data structures without needing this initial hint.)
*/


int xs_epoll_init(int size)
{
int epollfd = -1;

if(size == 0)
epollfd = xs_epoll_create(EPOLL_DEFAULT_SIZE);
else epollfd = xs_epoll_create(size);


if(epollfd < 0)
return EXIT_ERROR;

printf("epoll create success -> fd : %d", epollfd);

return epollfd;
}




static int xs_queue_init( block_queue_t *__q)
{
if(__q == NULL) return (-1);

#ifdef __VECTOR__

__q->queue = vector_init(xs_defult_thread_size);

#else
__q->size = 0;

#endif

xs_pthread_cond_init(&(__q->cond), NULL);
xs_pthread_mutex_init(&(__q->mutex), NULL);

return 0;
}

block_queue_t *xs_epoll_queue_create( void )
{
block_queue_t *__q;

__q = (block_queue_t*)xs_malloc(sizeof(block_queue_t));

assert(__q);

return ((xs_queue_init(__q) == 0) ? __q : NULL);
}

static inline void xs_network_epoll_loop(void* data)
{
int socket;

socket = *(int *)data;

printf("%d !\n", socket);

char buffer[BUFFER_SIZE];
xs_pthread_t id = pthread_self();
printf("thread id is: %ld", id);

/* We only send what recevied just now */
int length = xs_net_recv(socket, buffer, BUFFER_SIZE);
if(length)
{
xs_net_send(socket, buffer, strlen(buffer));
memset(buffer, 0, BUFFER_SIZE);
}
}


void *xs_handle_queue(void *param)
{
XS_PFUN func;
int fd;

block_queue_t* bque = (block_queue_t*)((block_queue_param_t*)param)->queue;
func =(XS_PFUN) ((block_queue_param_t*)param)->func;

xs_pthread_cond_init(&bque->cond, NULL);
xs_pthread_mutex_init(&bque->mutex, NULL);

for(;;)
{
if(xs_pthread_mutex_lock(&bque->mutex) == EXIT_OK)
{

xs_pthread_cond_wait(&bque->cond, &bque->mutex);
#ifdef __VECTOR__
if(bque->queue->active == 0)
{
xs_pthread_mutex_unlock(&bque->mutex);
continue;
}
else
{
fd = *(int *)(vector_lookup(bque->queue, 0));
}
#else
if(bque->size==0)
{
xs_pthread_mutex_unlock(&bque->mutex);
continue;
}
else
{

int i;
fd = bque->queue[0];

for(i = 0; i < bque->size - 1; ++i)
bque->queue[i] = bque->queue[i + 1];

bque->queue[bque->size-1] = 0;
bque->size--;
}
#endif
xs_pthread_mutex_unlock(&bque->mutex);
}

func((void *)&fd);
}
}

int xs_init_threads(void )
{
int i = 0, ret;
xs_pthread_t child_thread[g_xs_thread_count];
xs_pthread_attr_t child_thread_attr[g_xs_thread_count];

bqp.func = (void*)xs_network_epoll_loop;
bqp.queue = (void *)bq;

for( i = 0; i < g_xs_thread_count; ++i)
{
ret = xs_pthread_attr_init(&child_thread_attr[i]);
if(ret != 0) printf("error to init attr !\n");
pthread_attr_setdetachstate(&child_thread_attr[i], PTHREAD_CREATE_DETACHED);
if(pthread_create(&child_thread[i],&child_thread_attr[i], xs_handle_queue, (void *)&bqp) < 0 )
{
printf("pthread_create Failed : %s - %m\n",strerror(errno));
return 1;
}
}
return 0;
}

int xs_init_server(const char *name,short int port)
{
struct rlimit rt;
int server_socket = -1;

server_socket = xs_create_server(name, port);

rt.rlim_max = rt.rlim_cur = g_epoll_size;
if (setrlimit(RLIMIT_NOFILE, &rt) == -1)
{
printf("setrlimit - %m");
exit(1);
}

return server_socket;
}

static void xs_insert_queue(block_queue_t *bque, int *fd)
{
xs_pthread_mutex_lock(&bque->mutex);

#ifdef __VECTOR__
vector_set(bque->queue, fd);
#else
if(bque->size == g_xs_thread_count)
return;

bque->queue[bque->size] = *fd;
bque->size++;
if(bque->size > g_xs_thread_count) {
fprintf(stderr,"Queue size over folow.%ld", bque->size);
exit (1);
}
#endif

xs_pthread_cond_signal(&bque->cond);
xs_pthread_mutex_unlock(&bque->mutex);

}

static inline void xs_handler(void* fd)
{
printf("handler:fd => %d\n", *(int *)(fd));
xs_insert_queue(bq, (int*)fd);

}
int xs_epoll_entry()
{
int nfds, n;

g_serv_fd = xs_init_server(NULL, 11111);
printf("server thread [FD:%d] is ready for ...", g_serv_fd);


bq = xs_epoll_queue_create();
assert(bq);
if(xs_init_threads() == 0)
printf("Threads ready to use !");
g_epoll_fd = xs_epoll_init(g_epoll_size);
xs_epoll_add(g_epoll_fd, g_serv_fd, EPOLLIN | EPOLLET);

for(;;)
{
struct sockaddr_in local;
socklen_t length = sizeof(local);
int client = -1;

nfds = xs_epoll_wait(g_epoll_fd, xs_events, EPOLL_DEFAULT_SIZE, /*epoll_wait_indefinite*/-1);

for(n = 0; n < nfds; ++n)
{

if(xs_events[n].data.fd == g_serv_fd)
{
client = xs_net_accept(g_serv_fd, (struct sockaddr *)&local, &length);
if(client < 0) {
printf("%s",strerror(errno));
continue;
} else {
printf("add socket pool : %d", client);
set_nonblocking(client);
xs_epoll_add(g_epoll_fd, client, EPOLLIN | EPOLLOUT | EPOLLET);
client = -1;
}
}
else /* It's a client fd that needed to process */
xs_handler((void *)&xs_events[n].data.fd);
}
}
xs_pthread_mutex_destroy(&bq->mutex);
xs_pthread_cond_destroy(&bq->cond);
xs_close_socket(g_serv_fd);
xs_epoll_close(g_epoll_fd);

#ifdef __VECTOR__
vector_free(bq->queue);
#endif

xs_free(bq);
return 0;
}

int main(int argc,char *argv[])
{
extern int errno;
//argc = argc;
//argv = argv;

xs_epoll_entry();

return 0;
}