=======================================================================
.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; }
============================================================