我最近学会了如何使用automake,我有点恼火,我的编译命令来自一堆:
g++ -O2 -Wall -c fileName.cpp
Run Code Online (Sandbox Code Playgroud)
对于一堆:
depbase=`echo src/Unit.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
g++ -DHAVE_CONFIG_H -I. -I./src -g -O2 -MT src/Unit.o -MD -MP -MF $depbase.Tpo -c -o src/Unit.o src/Unit.cpp &&\
mv -f $depbase.Tpo $depbase.Po
Run Code Online (Sandbox Code Playgroud)
有没有办法清理它?我通常可以轻松地选择警告信息,但现在要阅读的文字墙是3倍大且更奇怪.
我知道我的旗帜是什么,因此只需要为每个文件说"编译xxx.cpp"就完美了.
我不确定这是我在这里不明白的gmake还是gcc.
我正在使用-MM和-MD选项为我正在使用的单元测试框架生成依赖性规则.特别:
$(TEST_OBJ_DIR)/%.d: $(TEST_SRC_DIR)/%.cpp
@$(CPPC) -MM -MD $< -o $@
@sed -i -e 's|\(.*\)\.o:|$(OBJ_DIR)/\1.o $(TEST_OBJ_DIR)/\1.d $(TEST_OBJ_DIR)/\1.o:|' $@
-include $(TEST_DEP_FILES)
Run Code Online (Sandbox Code Playgroud)
当我运行时make,在所有二进制文件链接(正确)后,我会在退出之前看到以下额外的(无法解释的)行
rm test/obj/dice.d test/obj/regex.o test/obj/inventoryContainer.d test/obj/color-string.d test/obj/dice.o test/obj/inventoryContainer.o test/obj/color-string.o test/obj/regex.d
Run Code Online (Sandbox Code Playgroud)
那个rm命令从哪里来?唯一的地方 - 任何地方 - 我rm在makefile中有一个命令是在clean指令中
test-clean:
rm -f $(TEST_BIN_FILES)
rm -f $(TEST_OBJ_DIR)/*.{a,d,o}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
我有一个创建目录的规则
bin:
-mkdir $@
Run Code Online (Sandbox Code Playgroud)
但是,在第一次生成目录后,我收到此输出:
mkdir bin
mkdir: cannot create directory `bin': File exists
make: [bin] Error 1 (ignored)
Run Code Online (Sandbox Code Playgroud)
是否有某些方法我只能在目录不存在时运行规则,或者在目录已存在时禁止输出?
这是我之前的问题的后续内容:SO 4403861,因为建议的解决方案打破了依赖关系,使makefile无用.我无法弄清楚为什么.
我正在使用gnu make 3.82我有一个规则,如果已经创建了obj目录:
objdir:=../obj
$(objdir)/%.o: %.C
$(COMPILE) -MM -MT$(objdir)/$(notdir $@) $< -o $(DEPDIR)/$(notdir $(basename $<).d )
$(COMPILE) -o $(objdir)/$(notdir $@ ) -c $<
Run Code Online (Sandbox Code Playgroud)
但是,如果obj目录不存在,则make失败.我希望make能够根据需要自动创建../obj,所以我添加了我认为非常简单的内容:
$(objdir)/%.o: %.C $(objdir)
$(COMPILE) -MM -MT$(objdir)/$(notdir $@) $< -o $(DEPDIR)/$(notdir $(basename $<).d )
$(COMPILE) -o $(objdir)/$(notdir $@ ) -c $<
$(objdir):
if [ ! -d $(objdir) ] ; then mkdir $(objdir) ; fi
Run Code Online (Sandbox Code Playgroud)
当我这样做时,每次都要强制编译.为什么?除非没有目录,否则不应该发生mkdir?为什么这个简单的改变破坏了依赖?
所以我遵循了高级自动依赖生成论文 -
Makefile:
SRCS := main.c foo.c
main: main.o foo.o
%.o: %.c
$(CC) -MMD -MG -MT '$@ $*.d' -c $< -o $@
cp $*.d $*.tmp
sed -e 's;#.*;;' -e 's;^[^:]*: *;;' -e 's; *\\$$;;' \
-e '/^$$/d' -e 's;$$; :;' < $*.tmp >> $*.d
rm $*.tmp
clean::
-rm *.o *.d main
-include $(SRCS:.c=.d)
Run Code Online (Sandbox Code Playgroud)
main.c:
#include "foo.h"
int main(int argc, char** argv) {
foo() ;
return 0 ;
}
Run Code Online (Sandbox Code Playgroud)
foo.h:
#ifndef __FOO_H__
#define __FOO_H__
void foo() …Run Code Online (Sandbox Code Playgroud) 我正在使用GNU make构建一组静态库,使用隐式make规则来执行此操作.这些规则运行ar(1)命令来更新库/存档.分析表明,如果我在构建期间使用-j选项来运行并行作业,则构建时间会减少.
不幸的是,GNU make手册有一个 http://www.gnu.org/software/make/manual/html_node/Archive-Pitfalls.html,它几乎说make不提供运行ar(1)的并发保护,并且因此它可以(并且确实)破坏档案.该手册进一步说明这可能在将来修复.
对此的一个解决方案是使用http://code.google.com/p/ipcmd,它基本上在运行命令之前执行信号量锁定,从而序列化构建存档的ar(1)命令.这个特殊的解决方案对我不利,因为我在Windows上使用基于mingw的交叉编译工具.
这个问题有更简单或更好的解决方案吗?
我有两个makefile,用于本机和交叉编译.它们之间唯一的区别是编译器名称:
# makefile CC = g++ ...
# makefile-cc CC = arm-linux-gnueabihf-g++ ...
为了进行本机编译,我执行make,进行交叉编译,我执行make -f makefile-cc.我希望有一个makefile,应该使用make本机编译执行,并make cross进行交叉编译.这样做的正确语法是什么,例如:
# makefile (C-like pseudo-code)
if cross
CC = arm-linux-gnueabihf-g++
else
CC = g++
我有一个项目,其中包括一个代码生成器,它只需一次调用代码生成器就可以从一个输入文件生成几个.c和.h文件.我有一个规则,其中.c和.h文件作为多个目标,输入文件作为先决条件,配方是代码生成器的调用.然后我有进一步的规则来编译和链接生成的.c文件.
这可以正常使用-j因子为1,但如果我增加j因子,我发现我得到了代码生成器的多次调用,直到-j因子或预期目标文件的数量,以最小者为准.这很糟糕,因为代码生成器的多次调用可能会因生成的代码被多次写入而导致失败.
我不打算在这里发布我的实际(大)代码,但我已经能够构建一个似乎表现出相同行为的小例子.
Makefile看起来像这样:
output.concat: output5 output4 output3 output2 output1
cat $^ > $@
output1 output2 output3 output4 output5: input
./frob input
clean:
rm -rf output*
对于此示例,我编写了一个简单的shell脚本,frob而不是代码生成器,它从一个输入文件生成多个输出文件:
#!/bin/bash
for i in {1..5}; do
{
echo "This is output${i}, generated from ${1}. input was:"
cat ${1}
} > output${i}
done
当我使用非统一-j因子运行此Makefile时,我得到以下输出:
$ make -j2 ./frob input ./frob input cat output5 output4 output3 output2 output1 > output.concat $
我们看到./frob这里被调用了两次,这很糟糕.有没有什么方法可以构造这个规则,使配方只被调用一次,即使是非统一-j因子?
我考虑过更改规则,以便只有一个预期的输出文件是目标,然后添加另一个没有配方的规则,使其目标是剩余的预期输出文件,先决条件是第一个预期的输出文件.但我不确定这会起作用,因为我不知道我是否可以保证生成文件的顺序,因此可能最终会产生循环依赖.
所以当你运行make而不改变它所说的任何依赖关系时target upto date.我很好奇它如何跟踪文件的变化,它是否有某种版本控制系统.如果是这样,这些文件存储在哪里?
我尝试在我当前的项目中实现一个非递归的make构建系统.我挣扎的是变量范围.目标特定变量不符合我的需要,因为通常变量定义目标而不是先决条件.我需要的是:
Makefile1:
SOMEVAR := original_value
include Makefile2
$(warning $(SOMEVAR))
Run Code Online (Sandbox Code Playgroud)
Makefile2:
#some magic here to do what I want and make me happy
SOMEVAR := included_value
#and maybe here
Run Code Online (Sandbox Code Playgroud)
我想要的输出是'original_value'.
有什么策略可以让它成真吗?
编辑:我目前唯一的解决方案是强制和组织自己将所有inlcudes放在每个特定Makefile的末尾并使用立即变量赋值:=