Linux C ++对主

时间:2015-09-18 09:20:11

标签: c++ linux makefile

我正在开发一个C ++项目,用语言刷新自己,并在使用make构建时遇到了一个相当奇怪(对我而言)的问题。

我的项目设置如下:

 bin/
 include/
 src/
 Makefile
 build.sh

src我目前有2个文件,loggerConfig.cpp和proxy.cpp。主要方法是在proxy.cpp中。我的Makefile包含以下内容,摘自this post

CC := g++
SRCDIR := src
BUILDDIR := build
TARGET := bin/proxy

SRCEXT := cpp
SOURCES := $(shell find $(SRCDIR) -type f -iname *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))

LINKFLAGS = -pthread -std=c++11
CFLAGS := -g -Wall -pedantic -std=c++11 -pthread
LIB := -lconfig++
INC := -I include


$(TARGET): $(OBJECTS)
    @echo " Linking..."
    @echo " $(CC) $^ -o $(TARGET) $(LIB)"; $(CC) $^ -o $(TARGET) $(LIB) $(LINKFLAGS)

$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
    @echo " Building..."
    @mkdir -p $(BUILDDIR)
    @echo " $(CC) $(CFLAGS) $(INC) -c -o $@ $<"; $(CC) $(CFLAGS) $(INC) -c -o $@ $<

clean:
    @echo " Cleaning..."; 
    @echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)

..PHONY: clean

一切都按预期工作,除非我的.cpp文件与我的Makefile位于同一目录中。因为我现在正在玩,所以在我将一些东西放入我的项目之前,我将在test.cpp文件中创建一个小的独立应用程序。当我这样做,并切换回使用make时,我将收到以下错误:

$ make clean ; make
 Cleaning...
 rm -f -r build bin/proxy
 Linking...
 g++  -o bin/proxy -lconfig++
/usr/lib/gcc/x86_64-redhat-linux/4.8.3/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [bin/proxy] Error 1

只需将test.cpp文件移动到一个目录即可解决问题并解决所有问题。有谁能解释为什么?我对make的理解相当简单,所以我对Google的内容感到茫然......

[编辑]

直接在shell中运行SOURCES列表的find命令后,我发现当test.cpp文件存在时,它没有返回任何结果。

$ ls
bin  build.sh  include  log  Makefile  src  test.cpp
$ find src -type f -iname *.cpp
$ mv test.cpp ../
$ find src -type f -iname *.cpp
src/proxy.cpp
src/loggerConfig.cpp

2 个答案:

答案 0 :(得分:1)

这是一个相当漂亮的Makefile,你可能会因为过度复杂而给自己带来麻烦。

我会更喜欢这样写:

TARGET=bin/proxy
SOURCES=loggerConfig proxy

$(TARGET): $(SOURCES:%=build/%.o)
    @echo " Linking..."
    $(CC) $^ -o $(TARGET) $(LIB) $(LINKFLAGS)

build/%.o: src/%.cpp
    @echo " Building..."
    test -d build || mkdir -p build
    $(CC) $(CFLAGS) $(INC) -c -o $@ $<

也许我只是一个小小的老派,但玩花哨变量替换的游戏很有趣,直到有人受伤,当我在那里屈服于诱惑时,我通常最后会后悔,并简化Makefile

特别是,这里有两个进一步的观察。

在动态生成SOURCES变量的情况下,这些源集似乎不太可能非常非常动态。添加文件时,不需要将名称添加到Makefile中,并且如果不这样做,程序将无法构建,因此没有遗忘的危险。

@echo foo bar; foo bar模式肯定只是在寻找麻烦!在某些时候,您必须调整其中一个foo bar部分而不调整另一部分,并且您将非常非常混淆。回复它执行的行,除非你用@前缀停止它,所以你似乎是通过环形路径合成默认行为。

答案 1 :(得分:0)

由于找到命令$SOURCES,问题是由make文件中的空find $(SRCDIR) -type f -iname *.$(SRCEXT))列表引起的。

要解决此问题,需要将该行更新为:

SOURCES := $(shell find $(SRCDIR) -type f -iname '*.$(SRCEXT)')

根据this answer,其原因是由于shell将*.cpp作为一个glob模式中断,并在传递之前将其扩展为匹配任何文件。实际上,正在运行的find命令是find src -type f -iname test.cpp,现在返回结果。