2012-06-30 69 views
0

我试图创建一个Makefile,其中包括输出一些library1.a,之后我将重新使用它来创建可执行文件。下面是我的困境:我想让这个过程变得通用,这样我就不必每次添加一些文件就编辑Makefile。下面是我的想法:从多个来源创建静态库

#Declare phony targets 
.PHONY: all clean build_utils 

#Compiler 
CXX = g++ 

#Flags 
CXXFLAGS = -Wall -Wextra -Wconversion -Werror -pedantic -std=c++0x -O2 

#Directories 
OUTPUT_DIR = _output/linux 
INTERMEDIATE_DIR = _intermediate/linux 
UTILS_DIR = utils 

all: $(OUTPUT_DIR)/libUtils.a 

$(OUTPUT_DIR)/libUtils.a: 
    ar rcs [email protected] $(INTERMEDIATE_DIR)/utils/$(patsubst %.cpp, %.o, $(wildcard $(UTILS_DIR)/ *.cpp)) 

#create .o files in %INTERMEDIATE_DIR/utils 
build_utils: $(UTILS_DIR)/ *.cpp $(UTILS_DIR)/ *.h 
    $(CXX) -c $(CXXFLAGS) $^ -o ## What must be placed here? ## 

所以,基本上,我想在一个临时目录中创建所有的目标文件,然后在libUtils.a存档,但我不能想出如何问编译器根据输入文件输出多个目标文件。基本上,我的标准强加每个.cpp文件,我应该得到一个对象文件,但我不知道如何做到这一点。我不想为每个.o文件创建一个单独的目标,因为它太乱了。

+0

虽然这不是直接回答您的问题,但我建议您查看cmake来为您生成Makefile文件。它似乎有你想实现内置的自动化类型。 – jpe

+0

@jpe cmake似乎比手动更复杂。我不得不投入几天的时间,现在我非常着急编译这个项目。 –

+0

在CMake中,实际上可以从大约三行或四行中匹配特定模式的所有文件创建一个库,这比Makefile文件要清晰得多。不是说,在Makefile中“手动”这样做肯定是一个坏主意,只是不要被CMake所看到,也许看起来复杂而复杂 - 它提供了很多很好的功能,但并不是很难习惯。 – sonicwave

回答

0

所以,几个小时的挖掘后,这里就是我设法想出:

#Build object files 
$(INTERMEDIATE_DIR)/$(UTILS_DIR)/%.o: $(UTILS_DIR)/%.cpp $(UTILS_DIR)/%.h 
    mkdir -p $(INTERMEDIATE_DIR)/$(UTILS_DIR) 
    $(CXX) $< $(LIBCXXFLAGS) -o [email protected] 

$(INTERMEDIATE_DIR)/$(FUNCTIONS_DIR)/%.o: $(FUNCTIONS_DIR)/%.cpp $(FUNCTIONS_DIR)/%.h 
    mkdir -p $(INTERMEDIATE_DIR)/$(FUNCTIONS_DIR) 
    $(CXX) $< $(LIBCXXFLAGS) -o [email protected] 


#create the library archives 
$(OUTPUT_DIR)/libUtils.a: $(patsubst %.cpp, $(INTERMEDIATE_DIR)/%.o, $(wildcard $(UTILS_DIR)/ *.cpp)) 
    ar rcs [email protected] $^ 
$(OUTPUT_DIR)/libFunctions.a: $(patsubst %.cpp, $(INTERMEDIATE_DIR)/%.o, $(wildcard $(FUNCTIONS_DIR)/ *.cpp)) 
    ar rcs [email protected] $^ 

#Builds the libraries 
libs: $(OUTPUT_DIR)/libUtils.a $(OUTPUT_DIR)/libFunctions.a 

#Main target 
all: libs 

关于它的好处是,我不必每次我加入的时间来编辑它文件。我认为通过建立目标文件的单个通用目标,可以使其变得更加抽象,但这似乎有点太过分了。

PS:谢谢Martin给我一个好主意,用什么来使用! :)

LE:似乎很难说服SO不尝试语法突出显示。即使<pre></pre>标签在处理/*时也不会有帮助...

1

您可以使用通配符规则类似下面分别编译每个C++源文件:

%.o: %.cpp 
    $(CXX) $< $(CXXFLAGS) [email protected] 

CXXFLAGS的末尾添加-c -o后。然后捕捉patsubst表达式的结果地方,例如:

OBJECTS = $(patsubst %.cpp, %.o, $(wildcard $(UTILS_DIR)/*.cpp)) 

...并有$(OUTPUT_DIR)/libUtils.a规则取决于$(OBJECTS)

+0

嗯......这看起来有点混乱,因为我希望我的.o文件在多个目录中生成... –

+0

@MihaiTodor,你应该在你的问题中提到你想要多个中间目录,而不仅仅是'utils /'。你有多个源目录,并且每个目录都需要在INTERMEDIATE_DIR中有相应的目录? – Beta

+0

是的,那是我的目标。不过,我设法以更“体面的方式”来做到这一点。我今天学到了很多关于Makefiles的知识,并且正在用我的解决方案添加一个答案。 –