2013-02-07 39 views
3

我的知识使自动工具(这我还没有使用此项目)是最基本的的时间。我有一个像下面的源代码层次结构,我试图找到构建方式尽可能无缝。多个目标断同一源树不同的预处理宏

该应用程序由app/src下各种子文件夹中的源代码组成。这些文件都是使用该文件夹根目录下的相应Makefile构建的。

然后,我有多个其他实用程序驻留在app/tools下的不同文件夹中,每个文件夹都有自己的Makefile。

app/src/module1/file1.cpp 
app/src/module1/file1.hpp 
app/src/module2/file2.cpp 
app/src/module2/file2.hpp 
app/src/module3/file3.cpp 
app/src/module3/file3.hpp 
app/src/main.cpp 
app/src/main.hpp 
app/src/Makefile 
app/tools/util1/file1.cpp 
app/tools/util1/file1.hpp 
app/tools/util1/Makefile 
app/tools/util2/file2.cpp 
app/tools/util2/file2.hpp 
app/tools/util2/Makefile 

,我的问题是,一些工具依赖于应用程序/ src源文件夹中的源文件,但有一个预处理宏EXTERNAL_TOOL启用。所以编译主应用程序和varous工具生成的目标文件不兼容。

当前要构建项目的每个部分,我不得不清理其中的源代码树。这是痛苦的,当然不是我想要的。解决这个问题最好的方法是什么?想法我有,我已经没有能够付诸实践是:

该项目的每个部分
  1. 编译目录
  2. 在构建外部工具,标记在主应用程序的目标文件不知何故(util.file1.o?)

我不太确定我有足够的时间和耐心来掌握make/autotools。可能其他构建工具之一(scons?cmake?)使这种任务更容易完成?如果是这样的话?

UPDATE:这是我必须得

SOURCES := util1.cpp util2.cpp util3.cpp \ 
    ../../src/module1/file1.cpp \ 
    ../../src/module1/file2.cpp \ 
    ../../src/module1/file3.cpp \ 
    ../../src/module2/file4.cpp \ 
    ../../src/module3/file5.cpp \ 
    ../../src/module3/file6.cpp \ 
    ../../src/module4/file7.cpp \ 
    ../../src/module4/file8.cpp \ 
    ../../src/module3/file9.cpp \ 
    ../../src/module4/file10.cpp \ 
    ../../src/module5/file11.cpp \ 
    ../../src/module3/file12.cpp \ 
    ../../src/module1/file13.cpp \ 
    ../../src/module3/file14.cpp \ 
    ../../src/module3/file15.cpp 

OBJECTS = $(join $(addsuffix .util/, $(dir $(SOURCES))), $(notdir $(SOURCES:.cpp=.o))) 

.PHONY: all mkdir 
all: util 
util: $(OBJECTS) 
    $(CXX) $(CXXFLAGS) $(OBJECTS) $(LIBS) -o util 

$(OBJECTS): | mkdir 
    $(CXX) -c $(CXXFLAGS) -o [email protected] $(patsubst %.o,%.cpp,$(subst .util/,,[email protected])) 

mkdir: 
    @mkdir -p $(sort $(dir $(OBJECTS))) 

clean: 
    [email protected] -f $(OBJECTS) util 
    [email protected] $(sort $(dir $(OBJECTS))) 2>/dev/null 

我经过广泛使用Google SO浏览来到这个问题。这似乎工作,但这部分并没有真正似乎特别好的(感觉就像一个黑客攻击的一位):

$(OBJECTS): | mkdir 
    $(CXX) -c $(CXXFLAGS) -o [email protected] $(patsubst %.o,%.cpp,$(subst .util/,,[email protected])) 

特别是我不是我创建的列表中的事实过于激烈早先来源的对象并添加后缀,只能在这里做相反的处理。我似乎无法以其他方式工作。

回答

5

CMake有add_definitionsremove_definitions命令。您可以使用它们为项目的不同部分定义宏:

# building tools # 
add_definitions(-DEXTERNAL_TOOL) 
add_subdirectory($TOOL1$ $BUILD_DIR$) 
add_subdirectory($TOOL2$ $BUILD_DIR$) 
... 

# building main app # 
remove_definitions(-DEXTERNAL_TOOL) 
add_executable(...) 
+0

通过CMake,你可以建立在同一个文件的两个版本,并放置在“结果”,在2个独立的目标迪尔斯,都只有一个build命令? – Brady

+0

@Brady你问,因为你的个人资料说'不能忍受cmake语法'? :) – hank

+0

我问,因为我好奇,如果它可以:)当我尝试cmake时,我想做变种构建,我很难得到它的工作,我不得不重建/重新生成makefiles这样做。这可能是由于我的无知,虽然:) – Brady

1

这可以通过SCons轻松完成。您肯定需要使用不同的预处理器宏构建的对象的构建目录层次结构。用SCons术语来说,像这样创建构建目录称为variant_dir。我会建议以下SCons的分层构建结构:

app/SConstruct 
app/src/module1/file1.cpp 
app/src/module1/file1.hpp 
app/src/module2/file2.cpp 
app/src/module2/file2.hpp 
app/src/module3/file3.cpp 
app/src/module3/file3.hpp 
app/src/main.cpp 
app/src/main.hpp 
app/src/SConscript_modules 
app/src/SConscript_main 
app/tools/util1/file1.cpp 
app/tools/util1/file1.hpp 
app/tools/util2/file2.cpp 
app/tools/util2/file2.hpp 
app/tools/SConscript 
app/build/main/ 
app/build/target1/modules/ 
app/build/target2/modules/ 
app/build/tools/utils/ 

为了能够建立与不同的预处理宏相同的源文件,你将需要建立相同的文件与几个不同的环境。这些env可以在src/module SConscript脚本中设置,或者从根SConstruct设置并传递下来。我更喜欢第二种选择,因为它会使src/module SCons脚本模块化,并且不知道(不可知)预处理器宏。

这是根构建脚本,创建不同的env的和编排子目录构建脚本:

应用程序/ SConstruct

defines1 = ['MACRO1'] 
defines2 = ['MACRO2'] 

env1 = Environment(CPPDEFINES = defines1) 
env2 = Environment(CPPDEFINES = defines2) 

includePaths = [ 
    'src/module1', 
    'src/module2', 
    'src/module3', 
] 
env1.Append(CPPPATH = includePaths) 
env2.Append(CPPPATH = includePaths) 

# Build different versions of the module libs 
SConscript('src/SConscript_modules', 
      variant_dir = '#build/target1/modules', 
      exports = {'env':env1}, 
      duplicate=0) 
SConscript('src/SConscript_modules', 
      variant_dir = '#build/target2/modules', 
      exports = {'env':env2}, 
      duplicate=0) 

# Build main with env1 
SConscript('src/SConscript_main', 
      variant_dir = '#build/main', 
      exports = {'env':env2}, 
      duplicate=0) 

# Build tools with env2 
SConscript('tools/SConscript', 
      variant_dir = '#build/utils', 
      exports = {'env':env2}, 
      duplicate=0) 

这是主 应用/ src目录生成脚本/ SConscript_main

Import('env') 

sourceFiles = ['main.cpp'] 
# If you want to modify the env here, Clone() it first, otherwise 
# the changes will be visible to all other SConscripts 
env.Program(target = 'main', source = sourceFiles) 

这是模块库的构建脚本,它会被称为两次,用不同的Env每次应用/ src目录/ SConscript_modules

Import('env') 

module1SourceFiles = ['file1.cpp'] 
module2SourceFiles = ['file2.cpp'] 
module3SourceFiles = ['file3.cpp'] 

# If you want to modify the env here, Clone() it first, otherwise 
# the changes will be visible to all other SConscripts 
env.Library(target = 'module1', source = module1SourceFiles) 
env.Library(target = 'module2', source = module2SourceFiles) 
env.Library(target = 'module3', source = module3SourceFiles) 
相关问题