假设你有一个带有两个伪目标的Makefile,'all'和'debug'.'debug'目标用于构建与'all'相同的项目,除了一些不同的编译开关(例如-ggdb).由于目标使用不同的编译开关,如果在两者之间切换,显然需要重建整个项目.但GNUmake自然不会认识到这一点.
所以,如果你输入,make all你会得到
Building ...
...
Run Code Online (Sandbox Code Playgroud)
如果你打字make debug,你就得到了
make: Nothing to be done for `debug'.
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:你如何在Makefile中实现一个干净的解决方案,注意到最后一个构建使用了不同的伪目标或不同的编译开关,而不是你想要的那个?如果它们不同,Makefile将重建所有内容.
我想像shell你可以说的宏一样自己制作一些东西$(shell command).
不幸的是,我还没有在网上找到任何关于如何做到这一点.
那可能吗?
我把tarball的软件版本放在一起,其中包括几个不同项目的输出.这些tarball本身被认为是一个版本.发布的tarball包括BOM(物料清单),其中列出了其中的所有项目及其关联的SHA1(git)签名.
为了更容易地重新创建这些tarball,我将一个make系统放在一起,逐行解析BOM,将存储库克隆到一个子目录中,检查指定的版本,然后执行构建.在我的BOM中说一行:
prog-a b5286f27d65ef20eb4508f76de5a1c57d8b21d85 git+ssh://git-user@localhost/~/prog-a
Run Code Online (Sandbox Code Playgroud)
存储库,如果尚未克隆,将被放入repos/prog-a,然后结帐完成(cd repos/prog-a; git checkout b5286f27d6),最后是make(make -C repos/prog-a).
我还没弄明白如何让gnu决定代码的签出版本是否已经构建了我需要的二进制文件.目前,每个子项目都被迫结账和重建.
如何向GNU make提供git repo的SHA1,以便它可以决定项目是否过时并需要更新(通过执行a git checkout)?
[编辑] 这是我的模式文件:
REPO_DIR=materials
BOM=$(shell sed -r 's/([^ ]+).+/\1/' bom)
BOM_DIR=$(shell sed -r 's_([^ ]+).+_$(REPO_DIR)/\1_' bom)
BOM_BLD=$(shell sed -r 's_([^ ]+).+_$(REPO_DIR)/\1/\1_' bom)
.PHONY: clean dist-clean
all: $(BOM)
clean:
@rm $(BOM) $(BOM_BLD) -rf
dist-clean: clean
@rm $(REPO_DIR)
.SECONDEXPANSION:
$(BOM): % : $(REPO_DIR)/$$*/$$*
@echo " CP $< $@"
@cp $< $@
$(BOM_BLD): % : $$(*D)
@echo " GIT …Run Code Online (Sandbox Code Playgroud) 我正在尝试制作一个Makefile,它使用特定于目标的变量来指定目标文件和最终可执行文件的输出目录.我们的想法是维护两个独立的二进制版本,一个'发布'版本和一个带有额外调试信息的'debug'版本.
我的问题是'make'每次都做一个干净的构建,即使我没有改变一件事.我很确定这是因为'make'是在'debug'或'release'目标的先决条件中的变量声明之前评估目标'corewars'的先决条件.
Makefile如下所示.
CXX=g++
LD=g++
LDFLAGS=
CXXFLAGS=-Iinclude -Wall -Wextra
OBJECTS=main.o Machine.o Core.o ProcessQueue.o Instruction.o
OUTPUT_DIR:=Test/
.PHONY: default
.PHONY: all
.PHONY: release
default: release
all: release
release: OUTPUT_DIR:=Release/
release: corewars
.PHONY: debug
debug: CXXFLAGS+=-DDEBUG -g
debug: OUTPUT_DIR:=Debug/
debug: corewars
corewars: $(OUTPUT_DIR) $(addprefix $(OUTPUT_DIR),$(OBJECTS))
$(LD) -o $(addprefix $(OUTPUT_DIR),corewars) $(addprefix $(OUTPUT_DIR),$(OBJECTS))
Release:
mkdir -p $@
Debug:
mkdir -p $@
%.o: %.cpp include/%.h
$(CXX) -c $(CXXFLAGS) $< -o $(OUTPUT_DIR)$@
.PHONY: clean
clean:
$(RM) -r Release
$(RM) -r Debug
Run Code Online (Sandbox Code Playgroud) 我的印象是我可以在GNU makefile中调用bash函数,但是似乎是错误的。这是一个简单的测试,我定义了此功能:
>type lsc
lsc is a function
lsc ()
{
ls --color=auto --color=tty
}
Run Code Online (Sandbox Code Playgroud)
这是我的Makefile:
>cat Makefile
all:
lsc
Run Code Online (Sandbox Code Playgroud)
这是我运行make的过程:
>make
lsc
make: lsc: Command not found
make: *** [all] Error 127
Run Code Online (Sandbox Code Playgroud)
我的印象错了吗?还是有任何环境设置问题?我可以在命令行中运行“ lsc”。
我有一组我想编译的.cpp文件.这些.cpp文件位于分层目录结构中.我希望相应的.o文件最终都在一个构建文件夹中.
这是我如何让GNU make枚举文件...
SRCS = \
$(wildcard $(CODE)/**/*.cpp) \
$(wildcard $(CODE)/AlgebraLibraries/**/*.cpp) \
$(wildcard $(CODE)/Calculator/Environments/**/*.cpp)
BARE_SRCS = $(notdir $(SRCS))
BARE_OBJS = $(BARE_SRCS:.cpp=.o)
OBJS = $(addprefix $(BUILD)/, $(BARE_OBJS))
Run Code Online (Sandbox Code Playgroud)
完成此操作后,我不知道如何创建将从.cpp文件创建.o文件的规则.直觉上,我想要做的是以下伪代码.
for i=0, N do # <-- a for-loop!
$(OBJS)[i]: $(SRCS)[i] # <-- the rule!
$(CPP) -c $(SRCS)[i] -o $(OBJS)[i] # <-- the recipe
end
Run Code Online (Sandbox Code Playgroud)
当然,这不是有效的GNU make代码,但我相信你理解我正在尝试做的事情.以下方法无效.
%.o: %.cpp
$(CPP) -c $< -o $@
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为GNU make匹配%符号,假设.o文件与.cpp文件并存.
我所知道的所有这些的替代方案,但将非常繁琐,是将所有规则作为明确的规则进行枚举.那是迟钝的!一定有更好的方法.
我一直在研究GNU make生成规则的能力,但如果没有内置逻辑,似乎没有办法做到这一点.如果我可以利用一些流控制语句来生成我想要制定的规则,那将是非常好的.这是否过多地要求GNU-make?
无论如何,有没有办法做我正在尝试用GNU make做的事情?如果是这样,怎么样?
谢谢您的帮助!
这让我疯狂.
对于并行make build(-j),您应该能够同步控制台输出.这是ref:
我正在使用GNU Make 3.82 for x86_64-redhat-linux-gnu
不同步的:
make -j8 all //not synchronized
Run Code Online (Sandbox Code Playgroud)
产量(我在这里使用eclipse-cdt managedbuild):
Building file: ../dome.c
Building file: ../main.c
Invoking: GCC C Compiler
gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"dome.d" -MT"dome.d" -o "dome.o" "../dome.c"
Invoking: GCC C Compiler
gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o "main.o" "../main.c"
Finished building: ../dome.c
Finished building: ../main.c
Building target: empty_linux
Invoking: GCC C Linker
gcc -o "empty_linux" ./dome.o ./main.o
Finished building target: …Run Code Online (Sandbox Code Playgroud) 来自文档:
.ONESHELL
如果.ONESHELL被提到作为目标,那么当构建目标时,配方的所有行将被赋予shell的单个调用,而不是单独调用每行(*note Recipe Execution:Execution.).
所以,一个makefile,如:
.ONESHELL :
all ::
echo 'foo
bar'
Run Code Online (Sandbox Code Playgroud)
跑步,我得到:
$ make
echo 'foo
/bin/sh: 1: Syntax error: Unterminated quoted string
makefile:4: recipe for target 'all' failed
make: [all] Error 2 (ignored)
Run Code Online (Sandbox Code Playgroud)
尝试,几乎相同的makefile,但是如果添加-前缀配方,忽略错误,记录:
要忽略配方行中的错误,请在行的文本开头(在初始选项卡之后)写一个" - ".在将行传递给shell以执行之前,将丢弃" - ".
makefile,如:
.ONESHELL :
all ::
-echo 'foo
bar'
Run Code Online (Sandbox Code Playgroud)
跑步,我得到:
$ make
echo 'foo
/bin/sh: 1: Syntax error: Unterminated quoted string
makefile:4: recipe for target 'all' failed
make: [all] Error 2 …Run Code Online (Sandbox Code Playgroud) 就我而言,我有requirements目标,该目标安装了所需的Python软件包test,并运行了测试,并取决于先前的测试。
安装依赖项是一项很长的操作,我希望仅在requirements.txt更改时才执行。我该如何实现?
这是我现在拥有的Makefile的简化示例:
.PHONY: test requirements
requirements: requirements.txt
pip install -r $<
test: tests/ | requirements
py.test $^
Run Code Online (Sandbox Code Playgroud) 我刚开始使用Google Protocol Buffers,我试图将协议缓冲编译器中的C++输出文件合并到我的项目中.到目前为止,我已经为我的项目使用了一个简单的makefile,它可以构建所有共享相同扩展名的源文件.我使用".cpp"作为源文件,但Google Protocol Buffers将其源代码输出为".pb.cc"文件.我需要能够将两种类型的源文件编译并链接到一个可执行文件中.
我一直在搜索和摆弄我的makefile几个小时,但没有成功.
我当前的Makefile:
PROGRAM_NAME=aserv
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g --std=c++14 -O3 -I/usr/local/include/
LDFLAGS=-g -L/usr/local/lib -L/usr/local/lib/boost
LDLIBS= -lrtaudio -pthread -lboost_system -lprotobuf
INSTALL_DIR = /usr/local/bin/
SRCS=$(wildcard *.cpp)
OBJS=$(subst .cpp,.o,$(SRCS))
all: $(PROGRAM_NAME)
$(PROGRAM_NAME): $(OBJS)
$(CXX) $(LDFLAGS) -o $(PROGRAM_NAME) $(OBJS) $(LDLIBS)
depend: .depend
.depend: $(SRCS)
rm -f ./.depend
$(CXX) $(CPPFLAGS) -MM $^>>./.depend;
clean:
$(RM) $(OBJS) $(PROGRAM_NAME) .depend
install:
cp $(PROGRAM_NAME) $(INSTALL_DIR)$(PROGRAM_NAME)
uninstall:
$(RM) $(INSTALL_DIR)$(PROGRAM_NAME)
dist-clean: clean
$(RM) *~ .depend
include .depend
Run Code Online (Sandbox Code Playgroud)
我还不太精通编写makefile,所以我只是不知道该怎么做才能使这个工作.
如果它有助于我在Ubuntu 16.04 beta上使用GNU make 4.1和gcc 5.3.1