makefile编写注意事项

=======================================================================

.PHONY有何作用

 .PHONY说明all是个“伪目标”,make不会生成“all”这个可执行文件,而是执行后面的多个目标

-fPIC 选项

-fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),
则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意
位置,都可以正确的执行。 这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。
https://blog.csdn.net/clirus/article/details/46990859

-Wall有何作用

选项可以打印出编译时所有的错误或者警告信息。这个选项很容易被遗忘,编译的时候,没有错误或者警告提示,以为自己的程序很完美,

其实,里面有可能隐藏着许多陷阱。变量没有初始化,类型不匹配,或者类型转换错误等警告提示需要重点注意,错误就隐藏在这些代码里面。

没有使用的变量也需要注意,去掉无用的代码,让整个程序显得干净一点。下次写Makefile的时候,一定加-Wall编译选项。


-M有什么作用。 gcc -M main.c
該選項默認打開了-E選項,-E參數的用處是使得編譯器在預處理結束時就停止編譯

- $@ : 表示一个规则中的目标.当规则中有多个目标时,$@ 所指的是其中任何造成规则的命令运行的目标
- $^ : 表示规则中的所有依赖项
- $< : 表示规则中的第一个依赖项


什么“$(@:%.o =%.d)”在makefile中是什么意思?
$(= =)执行 string replacement.
$@是 the name of the file being generated(目标).
所以$(@:%.o =%.d)是文件的名称,.o扩展名更改为.d.
此命令行为每个.o文件生成一个.d依赖项文件.

使一个Makefile同时生成多个可执行文件, 分别执行编译链接的步骤:

CXX := /opt/gnu/bin/g++
SUPPORT_EXT_DEPS := 0
INCLUDE := -I ./include
LDFLAGS := -L ./include/libzmq.a
LIBS := ./lib/libzmq.a

ifeq ($(DEBUG),1)
CXXFLAGS += -O0 -DDEBUG -D_DEBUG -g
else
CXXFLAGS += -O2 -DNDEBUG $(INCLUDE)
endif

OBJS := server.o client.o
DEPS := $(OBJS:.o=.d)
EXE := server client
#CLIENT := client

-include $(DEPS)

client: client.o
$(CXX) $(CXXFLAGS) -o client client.o $(LIBS) -lpthread

server: server.o
$(CXX) $(CXXFLAGS) -o server server.o $(LIBS) -lpthread

client.o: client.cpp
$(CXX) $(CXXFLAGS) -o $@ $<
server.o: server.cpp
$(CXX) $(CXXFLAGS) -o $@ $<

clean:
rm -f $(OBJS) $(DEPS) $(EXE)
@echo "clean"

=========================================================================

编译链接一个步骤

all: $(EXE)
$(EXE): $(OBJS)
$(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS) -lpthread

=========================================================================

编译链接分二个步骤

all: $(EXE)
$(OBJS): $(SRC)
$(CXX) $(CXXFLAGS) -o $@ -c $<

$(EXE): server.o
$(CXX) $< -o $@ $(LIBS) -lpthread

 ============测试文件===========================================================

server.cpp

#include <string>
#include <iostream>
#include <unistd.h>
#include "zmq.hpp"

int main()
{
zmq::context_t context(1);
zmq::socket_t socket(context, ZMQ_REP);
socket.bind("tcp://*:5555");
std::cout<< "setup zmq server" <<std::endl;
while(true){
zmq::message_t request;

socket.recv(&request);
std::cout<< "reveive hello" <<std::endl;
sleep(1);

zmq::message_t reply(5);
memcpy( (void *)reply.data(), "world", 5);
socket.send(reply);
}
return 0;

}

client.cpp

#include <zmq.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

int main (void)
{
void *context = zmq_init (1);

// Socket to talk to server
printf ("Connecting to hello world server…\n");
void *requester = zmq_socket (context, ZMQ_REQ);
zmq_connect (requester, "tcp://localhost:5555");

int request_nbr;
for (request_nbr = 0; request_nbr != 10; request_nbr++) {
zmq_msg_t request;
zmq_msg_init_size (&request, 5);
memcpy (zmq_msg_data (&request), "Hello", 5);
printf ("Sending Hello %d…\n", request_nbr);
zmq_msg_send (&request, requester, 0);
zmq_msg_close (&request);

zmq_msg_t reply;
zmq_msg_init (&reply);
zmq_msg_recv (&reply, requester, 0);
printf ("Received World %d\n", request_nbr);
zmq_msg_close (&reply);
}
zmq_close (requester);
zmq_term (context);
return 0;
}

============================================================

原文地址:https://www.cnblogs.com/7star/p/15693579.html