【问题标题】:Creating static library from multiple sources从多个来源创建静态库
【发布时间】:2012-06-30 13:31:50
【问题描述】:

我正在尝试创建一个 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 $@ $(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 文件创建单独的目标,因为它太乱了。

【问题讨论】:

  • 虽然这不是直接回答您的问题,但我建议您查看 cmake 为您生成 Makefile。它似乎具有您想要内置的自动化类型。
  • @jpe cmake 似乎比手动操作要复杂得多。我必须投入几天的时间,现在我急于编译这个项目。
  • 在 CMake 中,您实际上可以从匹配特定模式的所有文件创建一个库,大约三四行,这比 Makefile 更清晰易读。并不是说在 Makefile 中“手动”执行它一定是一个坏主意,只是不要被 CMake 认为可能看起来复杂而复杂 - 它提供了许多不错的功能,但并不难习惯.
  • @sonicwave 好吧,当您是程序员团队的一员并且大家都处于尝试找出最适合的工具的阶段时,也许使用它是个好主意对于这个特定的实现。另一方面,当你是团队中唯一的程序员并且每个人都想知道“为什么要花这么长时间来实现我们在 10 分钟内编写的这两个公式”,那么你需要让事情变得非常简单,而且,还可以扩展。是的,我本可以花半周时间阅读有关 cmake 的内容,但另一方面,我还需要编写代码……

标签: c++ linux makefile


【解决方案1】:

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

%.o: %.cpp
     $(CXX) $< $(CXXFLAGS) $@

在您的CXXFLAGS 末尾添加-c -o 之后。然后在某处捕获patsubst 表达式的结果,例如:

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

...并让$(OUTPUT_DIR)/libUtils.a 规则依赖于$(OBJECTS)

【讨论】:

  • 嗯...这看起来有点乱,因为我希望我的 .o 文件在多个目录中生成...
  • @MihaiTodor,您应该在问题中提到您想要多个中间目录,而不仅仅是utils/。您是否有多个源目录,并希望在INTERMEDIATE_DIR 中为每个目录提供一个对应的目录?
  • 是的,这就是我的目标。不过,我设法以一种更“体面的方式”来做到这一点。我今天学到了很多关于 Makefile 的知识,我正在用我的解决方案添加一个答案。
【解决方案2】:

所以,经过数小时的挖掘,这是我设法想出的:

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

$(INTERMEDIATE_DIR)/$(FUNCTIONS_DIR)/%.o: $(FUNCTIONS_DIR)/%.cpp $(FUNCTIONS_DIR)/%.h
    mkdir -p $(INTERMEDIATE_DIR)/$(FUNCTIONS_DIR)
    $(CXX) $< $(LIBCXXFLAGS) -o $@


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

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

#Main target
all: libs

它的好处是我不必每次添加文件时都对其进行编辑。我认为它可以比这更抽象,通过一个构建目标文件的通用目标,但这似乎有点太多了。

PS:感谢Martin 让我知道如何使用! :)

LE:似乎很难说服 SO 不要尝试进行语法高亮显示。在处理/* 时,甚至&lt;pre&gt;&lt;/pre&gt; 标签也无济于事...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    • 2023-04-01
    • 2012-08-29
    相关资源
    最近更新 更多