【发布时间】:2018-11-26 19:47:17
【问题描述】:
我正在尝试创建一个 Makefile,其中 make 只重新编译必要的 .cpp 文件。
默认情况下,如果我编辑 .cpp 效果很好,但是,当我编辑 .h 文件时,它只是忽略更改。
所以我读过-MD flag 和它的朋友-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;
}
【问题讨论】:
-
请发minimal reproducible example 仍然显示问题,您需要显示包含指令和文件夹结构的示例。
-
鉴于此信息,我们情不自禁。我认为您可以自己调试。首先,找到生成的
.d文件并查看它们。他们在正确的地方吗?那是针对每个srcdir/foo.c是否有srcdir/foo.d文件?内容看起来合理吗?.o文件的目标名称是否正确?先决条件路径是否正确?如果这看起来不错,则运行make -d(将大量输出重定向到文件)。找到流程 make 决定重建样本.o。它会准确地告诉您哪些文件已过期。对吗? -
@MadScientist
make -d确实在这里有所帮助。而且我了解这里发生了什么,请参阅我的编辑,实际上我每次都在重新安装库,因此它认为文件已根据其日期更改。我想我可以找到更新库的更好方法
标签: makefile