makefile编写注意事项

 

Makefile入门二、理解@^和$<     

ubuntu14.04 不重装更新CMake

CMake的hello world(一)使用CMake

windows下使用Cmake为自己创建的库添加版本信息

 

几个例子说清楚make 的赋值语句。

= 是最基本的赋值
:= 是覆盖之前的值
?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值

之前一直纠结makefile中“=”和“:=”的区别到底有什么区别,因为给变量赋值时,两个符号都在使用。网上搜了一下,有人给出了解答,但是本人愚钝,看不懂什么意思。几寻无果之下,也就放下了。今天看一篇博客,无意中发现作者对于这个问题做了很好的解答。解决问题之余不免感叹,有时候给个例子不就清楚了吗?为什么非要说得那么学术呢。^_^

      1、“=”

      make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。看例子:

            x = foo
            y = $(x) bar
            x = xyz

      在上例中,y的值将会是 xyz bar ,而不是 foo bar 。

      2、“:=”

      “:=”表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。

            x := foo
            y := $(x) bar
            x := xyz

      在上例中,y的值将会是 foo bar ,而不是 xyz bar 了。

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

.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中是什么意思?
(==)stringreplacement.@是 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;
}
复制代码

 

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

posted @   七星望  阅读(203)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示