我需要两次构建相同的源树,
1 - 使用正常的cflags构建项目二进制文件
2 - 使用cflags加上-fPIC来构建一个静态库,它将是某种用于开发项目动态模块的SDK。
只使用一个Makefile,完成此任务的最佳方法是什么?
做某种事情会很好:
all: $(OBJECTS)
lib_rule: $(OBJECTS)
CFLAGS += -fPIC
.cpp.o:
$(CC) -c $< -o $@ $(CFLAGS)
但显然无法做到。
由于
答案 0 :(得分:12)
我过去使用的一件事是不同的扩展名:
.cpp.o:
$(CC) -c $< -o $@ $(CFLAGS)
.cpp.lo:
$(CC) -c $< -o $@ $(CFLAGS) $(EXTRA_CFLAGS)
然后从.lo文件构建静态库,从.o文件构建二进制文件:
prog: a.o b.o
libsdk.a: a.lo b.lo
假设您使用的是GNU Make,您可以使用一些内置函数来只维护一次对象列表:
OBJS = a.o b.o
LOBJS = $(patsubst %.o, %.lo, $(OBJS))
答案 1 :(得分:7)
GNU make还提供“特定于目标的变量值”。请考虑以下Makefile:
# Makefile
CFLAGS := My Cflags
all: $(OBJECTS)
@echo "$@ CFLAGS is: " $(CFLAGS)
lib_rule: CFLAGS += extended by -fPIC
lib_rule: $(OBJECTS)
@echo "$@ CFLAGS is: " $(CFLAGS)
# Makefile - end.
$ make all
所有CFLAGS都是:我的Cflags
$ make lib_rule
lib_rule CFLAGS是:我的Cflags扩展为-fPIC
$
(请注意:如果您复制并粘贴示例,请记住在命令行前面重新添加tabstops。我总是被它抓住。)
答案 2 :(得分:2)
我没有将已编译的.o
文件放在与源相同的目录中,而是在带标签的子目录中创建它们。在您的情况下,您可以将静态库文件创建为source_dir/lib/*.o
,将普通文件创建为source_dir/bin/*.o
。在设置唯一的CFLAGS
后,在不同的构建目标中,只需生成一个DIR_NAME
值,其中包含相应子文件夹的名称。在为构建和链接时创建编译器使用的路径时,可以使用此变量。
答案 3 :(得分:0)
在一个不同的制作工具如CMake中,你可以更容易地表达这样的东西。
例如,你可以做到
set(sources ABC.cpp DEF.cpp XYZ.cpp)
ADD_LIBRARY(mylib STATIC ${sources})
add_executable(myExecutable ${sources} main.cpp)
或者,你可以通过在目录的逻辑父代中多次包含它来重复构建具有不同标志的同一目录,即
set(MyTweakFlag 2)
add_subdirectory("libDir" "libDir2")
set(MyTweakFlag 3)
add_subdirectory("libDir" "libDir3")
...然后在子目录中使用if()
或whatnot来设置正确的标志。
特别是如果你有很多这样的配置,使用make变得非常脆弱; make将无法正确找到递归make dependancies的传递闭包(当然也无法正确找到makefile本身的依赖性 - 如果你更改了标志,那么)如果你要做复杂的makefile魔术:用它来做一个更好的工具!
(CMake恰好就是我所取代的,但当然还有其他各种替代方案)