使用makefile进行链接的目标文件生成和最佳实践 - C ++

时间:2009-04-23 05:42:53

标签: c++ makefile

背景

我刚刚开始在LINUX上进行C ++编程。在我的上一个问题中,我询问了为大型应用程序使用makefile的最佳实践。 “SO”用户建议阅读Miller关于递归makefile的文章并避免makefile递归(我使用的是递归makefile)。

我跟随米勒并创建了如下所示的makefile。以下是项目结构

root
...makefile
...main.cpp
...foo
......foo.cpp
......foo.h
......module.mk

我的makefile如下所示

#Main makefile which does the build

CFLAGS =
CC = g++
PROG = fooexe

#each module will append the source files to here
SRC :=

#including the description
include foo/module.mk

OBJ := $(patsubst %.cpp, %.o, $(filter %.cpp,$(SRC))) main.o

#linking the program
fooexe: $(OBJ)
    $(CC) -o $(PROG) $(OBJ)

%.o:
    $(CC) -c $(SRC)

main.o:
    $(CC) -c main.cpp

depend:
    makedepend -- $(CFLAGS) -- $(SRC)

.PHONY:clean
clean:
    rm -f *.o

以下是 foo 目录中的 module.mk

SRC += foo/foo.cpp

当我运行 make -n 时,我得到以下输出。

g++ -c  foo/foo.cpp
g++ -c main.cpp
g++ -o fooexe  foo/foo.o main.o

问题

  • 我应该在哪里创建对象(.o)文件?单个目录中的所有目标文件或每个目标文件都在自己的模块目录中?我的意思是哪个是生成foo.o的最佳位置?是在foo目录还是根目录(我的示例在根目录中生成)?
  • 在提供的示例中, g ++ -c foo / foo.cpp 命令在根目录中生成.o文件。但是当链接( g ++ -o fooexe foo / foo.o main.o )时,它正在寻找 foo / foo.o 。我怎么能纠正这个?

任何帮助都会很棒

4 个答案:

答案 0 :(得分:1)

  
      
  • 我应该在哪里创建对象(.o)文件?单个目录中的所有目标文件或每个目标文件都在自己的模块目录中?我的意思是哪个是生成foo.o的最佳位置?是在foo目录还是根目录(我的示例在根目录中生成)?
  •   

我发现调查失败的构建更容易在文件级目录下的单独目录中本地化目标文件。

foo
    |_ build
    |_ src 

根据项目的大小,这些目标文件被分组以形成更高级别的组件,依此类推。所有组件都转到主构建目录,该目录可以运行主应用程序(具有所有依赖库等)。

  
      
  • 在提供的示例中,g ++ -c foo / foo.cpp命令在根目录中生成.o文件。但是当链接(g ++ -o fooexe foo / foo.o main.o)时,它正在寻找foo / foo.o。我怎么能纠正这个?
  •   

使用:

 g++ -o fooexe  foo.o main.o

答案 1 :(得分:0)

你能为自己做的最好的事情就是使用比Make更好的东西。 SCons是我在POSIX系统上的首选工具。 Boost还有一个非常灵活的构建工具,但我很难绕过它。

哦,如果你想使用make,请继续构建递归makefile。这真的不是什么大不了的事。在过去的三年里,我使用了大量的递归makefile进行了一个巨大的项目,它工作得很好。

答案 2 :(得分:0)

+1代表SCons 我也在使用SCons。它会为您扫描依赖项,它只会在源更改时重建,因为它使用加密哈希值而不是时间戳。

在我的SCons中,将对象生成并行目录到源(以启用多个构建,如32位和64位的组合,发布和调试):

src
.build
  linux
    i686
      debug
      release
    x86_64
      debug
      release

答案 3 :(得分:0)

关于对象和其他生成的临时文件,我将它们放在一个完全独立于源的目录中(即,在从备份和修订控制中排除的目录下)。在项目或makefile中设置可能稍微麻烦一点,但它可以节省打包源的时间,并且更容易进行干净的备份和版本控制。

我为与源的子目录结构匹配的目标文件创建子目录结构。通常,我的每个库和程序都有一个单独的子目录。

此外,我还使用多个编译器(和版本)和多个操作系统,因此我将在每个编译器(具有较新版本的标准和供应商库)的目录下重现目标文件目录结构以防止对象包含不匹配的头文件版本的文件。