Makefile - 通配符和配方构建

时间:2017-10-12 18:18:43

标签: c linux gcc makefile

我有以下makefile

# See gcc/clang manual to understand all flags
CFLAGS += -std=c99 # Define which version of the C standard to use
CFLAGS += -Wall # Enable the 'all' set of warnings
CFLAGS += -Werror # Treat all warnings as error
CFLAGS += -Wshadow # Warn when shadowing variables
CFLAGS += -Wextra # Enable additional warnings
CFLAGS += -O2 -D_FORTIFY_SOURCE=2 # Add canary code, i.e. detect buffer overflows
CFLAGS += -fstack-protector-all # Add canary code to detect stack smashing

# We have no libraries to link against except libc, but we want to keep
# the symbols for debugging
LDFLAGS = -rdynamic

# external libs
# par défaut les chemins classiques

LDFLAGS += -I$(HOME)/local/include
LDFLAGS += -L$(HOME)/local/lib

# Default compiler
CC=gcc

# folders
SOURCE_FOLDER=src
TESTS_FOLDER=tests
PAQUET_FOLDER=paquet
SEND_RECEIVE_DATA_FOLDER=sendAndReceiveData
CLIENT_FOLDER=client
SERVER_FOLDER=server

# folder of sources
PAQUET_FULL_PATH=$(SOURCE_FOLDER)/$(PAQUET_FOLDER)
SEND_RECEIVE_DATA_FULL_PATH=$(SOURCE_FOLDER)/$(SEND_RECEIVE_DATA_FOLDER)
CLIENT_FULL_PATH=$(SOURCE_FOLDER)/$(CLIENT_FOLDER)
SERVER_FULL_PATH=$(SOURCE_FOLDER)/$(SERVER_FOLDER)

# sources files
# On prend tout
PACKET_SOURCES = $(wildcard $(PAQUET_FULL_PATH)/*.c)
SEND_RECEIVE_DATA_SOURCES = $(wildcard $(SEND_RECEIVE_DATA_FULL_PATH)/*.c)
CLIENT_SOURCES = $(wildcard $(CLIENT_FULL_PATH)/*.c)
SERVER_SOURCES = $(wildcard $(SERVER_FULL_PATH)/*.c)

# objects

PACKET_OBJECTS=$(PACKET_SOURCES:.c=.o)
SEND_RECEIVE_DATA_OBJECTS=$(SEND_RECEIVE_DATA_SOURCES:.c=.o)
CLIENT_OBJECTS=$(CLIENT_SOURCES:.c=.o)
SERVER_OBJECTS=$(SERVER_SOURCES:.c=.o)

# another things

# Default target
all: clean server client

client: $(CLIENT_OBJECTS) $(PACKET_OBJECTS); \
        $(CC) $(CFLAGS) $(CLIENT_OBJECTS) $(LDFLAGS);

server: $(SERVER_OBJECTS) $(PACKET_OBJECTS); \
        $(CC) $(CFLAGS) $(SERVER_OBJECTS) $(LDFLAGS);

$(PACKET_OBJECTS): $(PACKET_OBJECTS); \
        $(CC) $(CFLAGS) -lz $(PACKET_OBJECT) $(LDFLAGS);

tests: $(PACKET_OBJECTS) $(TESTS_OBJECTS); \
        $(CC) $(CFLAGS) -lcunit $(LDFLAGS);

.PHONY: clean

clean:
    @rm -f *.o

我收到了这条消息:

  

make:Circular src / paquet / packet_implem.o< -   src / paquet / packet_implem.o依赖项已丢弃。 \                   gcc -std = c99 -Wall -Werror -Wshadow -Wextra -O2 -D_FORTIFY_SOURCE = 2 -fstack-protector-all -lz -rdynamic -I / home / jy95 / local / include -L / home / jy95 / local / lib; /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:In   函数_start': (.text+0x20): undefined reference to main'   collect2:错误:ld返回1退出状态Makefile:71:recipe for   target'src / paquet / packet_implem.o'失败make:***   [src / paquet / packet_implem.o]错误1

我想要的是什么:

1)建立依赖项(PACKET_SOURCES)和(SEND_RECEIVE_DATA_SOURCES)
2)使用步骤1中的依赖项构建客户端和服务器 3)可执行文件“client”将位于文件夹的根目录下。

如何更正错误?

2 个答案:

答案 0 :(得分:1)

使用-c生成对象而不尝试生成可执行文件,这样您就不需要主

    <activity android:name="your_package_name.MainActivity"/>

我认为您的SERVER_OBJECTS

也可能需要这样的规则
$(PACKET_OBJECTS): $(PACKET_OBJECTS); \
        $(CC) -c $(CFLAGS) -lz $(PACKET_OBJECT) $(LDFLAGS);

答案 1 :(得分:1)

此规则中出现问题:

$(PACKET_OBJECTS): $(PACKET_OBJECTS); \
        $(CC) $(CFLAGS) -lz $(PACKET_OBJECT) $(LDFLAGS);

这表示$(PACKET_OBJECTS)扩展中的每个目标都取决于$(PACKET_OBJECTS)扩展中的每个目标。这给了很多依赖循环,特别是它为你提供了一个元素循环的目标文件,具体取决于它们自己。

事实上,这条规则在其他几个方面存在问题:

  • 事实上,配方并没有创建任何规则的指定目标
  • 相反,它尝试目标文件(见下文)一起链接到一个可执行文件中,为结果指定默认名称(可能是a.out)。
  • 配方引用未定义的变量$(PACKET_OBJECT)。我想这可能是$(PACKET_OBJECTS)的拼写错误。相反,如果您指的是$(PACKET_OBJECTS)中给出的当前目标,那么拼写为$@
  • 不仅目标文件肯定不是每个都有自己的先决条件,它们也没有彼此作为先决条件。每个对象的依赖关系应该是它们对应的源。
  • 如果您确实要将此规则用于构建目标文件,则配方不需要指定要链接的库(例如-lz),也可能不应该这样做。

您可以完全删除该规则,从而获得更好的机会,这是相当不错的。您可能希望将-lz添加到LDFLAGS;否则它就会丢失。

此外,

  • 您可能想要移动-I$(HOME)/local/include选项:它不属于LDFLAGS,并且不会在那里起作用。如果您需要,请将其改为CPPFLAGS,或者CFLAGSINCLUDES

  • 构建可执行目标的各种规则应提供指定要构建的目标名称的选项。您可以将其拼写为&#34; -o $@&#34;,

  • clean目标作为all的先决条件包含在内是非常规的。如果您在未指定目标的情况下运行make,它将始终从头开始重建所有内容。大多数人宁愿只按要求这样做。

  • 您的all目标未构建名为&#34;所有&#34;的目标,因此它也应声明为.PHONY

很可能还有更多,但我会留下让你理清。