如何在Makefile中正确使用-MD标志

时间:2018-11-24 00:24:34

标签: makefile

我正在尝试创建一个Makefile,其中make只重新编译必要的.cpp文件。

默认情况下,如果我编辑.cpp会很好用,但是,当我编辑.h文件时,它只会忽略更改。

因此,我已经读过-MD标志及其朋友-MP(用于避免在输入make时出现错误)。

但是,如果使用-MMD,我似乎无法使其正常工作,但是它在编写与该项目一起发展的库时也依赖于系统包含。因此,如果我更新了库头文件并重新安装了库文件,则在主项目中键入make应该会重新编译包含已更改头文件的文件。

在使用-MMD标志时,它-不按预期-不会重新编译项目,但是,使用-MD标志,它会重新编译所有内容。实际上,-MD每次都会重新编译所有内容,即使没有任何更改。

以下是重现该问题的最小项目结构:

./ Makefile:

all: build

re: clean build

build: build_lib install_lib build_client

build_lib:
    $(MAKE) -C lib
    $(MAKE) install -C lib

build_client:
    $(MAKE) -C client

install_lib:
    $(MAKE) install -C lib


.PHONY: clean
clean: clean_lib clean_client

clean_lib:
    $(MAKE) clean -C lib

clean_client:
    $(MAKE) clean -C client

./ client / Makefile:

CC = g++
INC = -I../lib
CXXFLAGS = -Wall $(INC) -g -MD -MP
EXEC_NAME = ../test

src = $(shell find $(SOURCEDIR) -name '*.cpp')
obj = $(src:.cpp=.o)

LIBRARIES = -ltest_lib
LDFLAGS = -rdynamic $(LIBRARIES)

all: $(EXEC_NAME)

re: clean $(EXEC_NAME)

$(EXEC_NAME): $(obj)
    $(CC) -o $@ $^ $(LDFLAGS)
-include $(obj:.o=.d)

.PHONY: clean
clean:
    rm -f $(obj) $(EXEC_NAME)

./ lib / Makefile:

.PHONY : clean

CXXFLAGS= -fPIC -g -Itest_lib/include -MMD -MP
LDFLAGS= -shared

SOURCES = $(shell find $(SOURCEDIR) -name '*.cpp')
HEADERS = $(shell find $(SOURCEDIR) -name '*.h')
OBJECTS=$(SOURCES:.cpp=.o)

TARGET=libtest_lib.so
INC_FOLDER=test_lib/include
CUR_DIR = $(shell pwd)

all: $(TARGET)

install:
    sudo rm -rf /usr/local/lib/libtest_lib.so && sudo ln -s $(CUR_DIR)/$(TARGET) /usr/local/lib/libtest_lib.so
    sudo rm -rf /usr/local/include/test_lib && sudo cp -r $(INC_FOLDER) /usr/local/include/test_lib

clean:
    rm -f $(OBJECTS) $(TARGET)

$(TARGET) : $(OBJECTS)
    $(CC) $(CFLAGS) $(OBJECTS) -o $@ $(LDFLAGS)
-include $(OBJECTS:.o=.d)

./ client / main.cpp:

#include "bar.h"

int main()
{
    Bar b;

    b.sayHello();
    b.sayBye();

    return 0;
}

./ client / bar.h

#ifndef __BAR__
#define __BAR__

#include <test_lib/foo.h>
#include <iostream>

struct Bar : public Foo
{
    Bar() {};
    ~Bar() {};

    void sayBye() const {
        std::cout << "Bye " << name << "..." << std::endl;
    };
};

#endif

./ lib / test_lib / include / foo.h

#ifndef __FOO__
#define __FOO__

struct Foo
{
    const char *name;

    Foo(const char *name = "world");
    ~Foo();

    void sayHello() const;
};

#endif

./ lib / test_lib / src

#include "foo.h"
#include <iostream>

Foo::Foo(const char *name) : name(name) {}
Foo::~Foo() {}

void Foo::sayHello() const
{
    std::cout << "Hello " << name << " !" << std::endl;
}

1 个答案:

答案 0 :(得分:0)

问题是我一直都在/usr/local中复制库头,所以文件变得新了,然后客户使认为库的每个头都已更改。

此问题的一个简单解决方法是在库Makefile中替换以下行:

sudo rm -rf /usr/local/include/test_lib && sudo cp -r $(INC_FOLDER) /usr/local/include/test_lib

作者

sudo rm -rf /usr/local/include/test_lib && sudo ln -s $(CUR_DIR)/$(INC_FOLDER) /usr/local/include/test_lib

另一方面,所提供的示例缺少清除规则上的.d文件的删除。