在 makefile 的开头强制脚本到 运行,并显示其输出
force a script to run at the beginning of a makefile, and display its output
我有一个脚本可以生成一个 version.h
文件,其中包含有关特定构建的各种详细信息
脚本运行的各种命令,例如:
readonly VERSION=$(git describe --always --dirty --long --tags)
readonly NUM_COMMITS=$(git rev-list HEAD | wc -l | bc)
readonly BRANCH=$(git rev-parse --abbrev-ref HEAD)
readonly AHEAD_BY=$(git log --oneline origin/${BRANCH}..${BRANCH} | wc -l | bc)
readonly NUM_UNTRACKED=$(git ls-files --exclude-standard --others --full-name -- . | wc -l | bc)
readonly HOSTNAME=$(hostname)
然后写入一个临时文件,检查先前生成的文件,如果它们不同,则用新文件覆盖旧的 version.h
。
#pragma once
/*
* Version information
*
* - This is a generated file - do not edit
*/
namespace foo { namespace app {
static const char VERSION[] = "26b75cd";
static const char NUM_COMMITS[] = "224";
static const char BRANCH[] = "master";
static const char AHEAD_BY[] = "0";
static const char NUM_UNTRACKED[] = "0";
static const char USER[] = "steve";
static const char HOSTNAME[] = "steve-linux";
static const char BUILD_VARIANT[] = "debug";
static const char BUILD_DATE[] = __DATE__ " " __TIME__;
}}
它还会在文件更新时打印到标准输出
version updated: 26b75cd
版本脚本应该是第一个 运行,并且每次调用 makefile 时都应该是 运行。
目前,我通过在 makefile
中使用 简单扩展变量 来实现这一点
new_ver := $(shell ./app/gen_version.sh $(BUILD))
它有效,但是脚本的任何输出都被捕获在 new_var
中,我无法显示该输出。
这是一个可以接受的权衡(不显示新版本),但在理想情况下,我想显示脚本输出。
我不确定添加到默认 all
目标的 .PHONY
目标是否有效,因为每个应用程序都有自己的目标,因此您可以只构建该目标。
define do-make-bin
binaries += $(addprefix $(BIN_DIR),)
bin_sources +=
# a target so users can call 'make <bin-name>' and build only the bin and its dependencies
: $(addprefix $(BIN_DIR),)
# the target to build the actual binary
$(addprefix $(BIN_DIR),): $(call src_to_obj,) $(addsuffix .so,$(addprefix $(LIB_DIR)lib,)) $(addsuffix .a,$(addprefix $(LIB_DIR)lib,))
@$(CXX) $(call src_to_obj,) -L/usr/lib -L$(SDK_LIB_DIR) -L$(LIB_DIR) $(TARGET_LINK_FLAGS) -Wl$(,)-Bstatic $(addprefix -l,) $(addprefix -l,) -Wl$(,)-Bdynamic -Wl$(,)-rpath$(,)$(RPATH) $(linkpath) -L$(LIB_DIR) $(sdk_libs) $(tcmalloc_libs) -lpthread -lrt $(addprefix -l,) $(addprefix -l,) -rdynamic -o $$@
endef
调用make foo
应该还是会检查version.h
是否需要更新
当目标没有先决条件并且作为文件存在时,什么也不会发生。您需要的是在创建临时文件时设置条件先决条件。您可以使用 gnu/make.
的 wildcard
函数
如果临时文件被调用 version.new.h
并且假设脚本检查 version.h
和 version.new.h
之间的差异。如果它们相同,则将其删除。然后你可以使用类似的东西:
version.h : $(wildcard version.new.h)
mv -f version.new.h version.h
为了验证 version.h 是否首先创建,您应该拆分作业。
然后确保第一份工作先运行。 Makefile
代码示例是:
all: version_h other_staff
.PHONY: version_h
version_h:
./app/gen_version.sh $(BUILD)
$(MAKE) version.h
version.h : $(wildcard version.new.h)
mv -f version.new.h version.h
other_staff: $(EXE) $(LIBS)
如果您将自己限制在正常的 makefile 方法中,确保它在每个目标之前运行的唯一方法是将内容放入配方中,然后使构建该内容的目标成为 [=17= 的先决条件]您的 makefile 中的每个目标。虽然此 可以 以不会导致每次都重建所有内容的方式完成,但它很恶心。另外,它不会让你把输出放入像 new_ver
这样的变量中(你说你想显示它,但你没有说你是否也需要它在变量中)。
但是,如果唯一的问题是您没有显示 new_ver
的值,那 很容易解决:
new_ver := $(shell ./app/gen_version.sh $(BUILD))
$(info $(new_ver))
我有一个脚本可以生成一个 version.h
文件,其中包含有关特定构建的各种详细信息
脚本运行的各种命令,例如:
readonly VERSION=$(git describe --always --dirty --long --tags)
readonly NUM_COMMITS=$(git rev-list HEAD | wc -l | bc)
readonly BRANCH=$(git rev-parse --abbrev-ref HEAD)
readonly AHEAD_BY=$(git log --oneline origin/${BRANCH}..${BRANCH} | wc -l | bc)
readonly NUM_UNTRACKED=$(git ls-files --exclude-standard --others --full-name -- . | wc -l | bc)
readonly HOSTNAME=$(hostname)
然后写入一个临时文件,检查先前生成的文件,如果它们不同,则用新文件覆盖旧的 version.h
。
#pragma once
/*
* Version information
*
* - This is a generated file - do not edit
*/
namespace foo { namespace app {
static const char VERSION[] = "26b75cd";
static const char NUM_COMMITS[] = "224";
static const char BRANCH[] = "master";
static const char AHEAD_BY[] = "0";
static const char NUM_UNTRACKED[] = "0";
static const char USER[] = "steve";
static const char HOSTNAME[] = "steve-linux";
static const char BUILD_VARIANT[] = "debug";
static const char BUILD_DATE[] = __DATE__ " " __TIME__;
}}
它还会在文件更新时打印到标准输出
version updated: 26b75cd
版本脚本应该是第一个 运行,并且每次调用 makefile 时都应该是 运行。
目前,我通过在 makefile
中使用 简单扩展变量 来实现这一点new_ver := $(shell ./app/gen_version.sh $(BUILD))
它有效,但是脚本的任何输出都被捕获在 new_var
中,我无法显示该输出。
这是一个可以接受的权衡(不显示新版本),但在理想情况下,我想显示脚本输出。
我不确定添加到默认 all
目标的 .PHONY
目标是否有效,因为每个应用程序都有自己的目标,因此您可以只构建该目标。
define do-make-bin
binaries += $(addprefix $(BIN_DIR),)
bin_sources +=
# a target so users can call 'make <bin-name>' and build only the bin and its dependencies
: $(addprefix $(BIN_DIR),)
# the target to build the actual binary
$(addprefix $(BIN_DIR),): $(call src_to_obj,) $(addsuffix .so,$(addprefix $(LIB_DIR)lib,)) $(addsuffix .a,$(addprefix $(LIB_DIR)lib,))
@$(CXX) $(call src_to_obj,) -L/usr/lib -L$(SDK_LIB_DIR) -L$(LIB_DIR) $(TARGET_LINK_FLAGS) -Wl$(,)-Bstatic $(addprefix -l,) $(addprefix -l,) -Wl$(,)-Bdynamic -Wl$(,)-rpath$(,)$(RPATH) $(linkpath) -L$(LIB_DIR) $(sdk_libs) $(tcmalloc_libs) -lpthread -lrt $(addprefix -l,) $(addprefix -l,) -rdynamic -o $$@
endef
调用make foo
应该还是会检查version.h
是否需要更新
当目标没有先决条件并且作为文件存在时,什么也不会发生。您需要的是在创建临时文件时设置条件先决条件。您可以使用 gnu/make.
的wildcard
函数
如果临时文件被调用 version.new.h
并且假设脚本检查 version.h
和 version.new.h
之间的差异。如果它们相同,则将其删除。然后你可以使用类似的东西:
version.h : $(wildcard version.new.h)
mv -f version.new.h version.h
为了验证 version.h 是否首先创建,您应该拆分作业。
然后确保第一份工作先运行。 Makefile
代码示例是:
all: version_h other_staff
.PHONY: version_h
version_h:
./app/gen_version.sh $(BUILD)
$(MAKE) version.h
version.h : $(wildcard version.new.h)
mv -f version.new.h version.h
other_staff: $(EXE) $(LIBS)
如果您将自己限制在正常的 makefile 方法中,确保它在每个目标之前运行的唯一方法是将内容放入配方中,然后使构建该内容的目标成为 [=17= 的先决条件]您的 makefile 中的每个目标。虽然此 可以 以不会导致每次都重建所有内容的方式完成,但它很恶心。另外,它不会让你把输出放入像 new_ver
这样的变量中(你说你想显示它,但你没有说你是否也需要它在变量中)。
但是,如果唯一的问题是您没有显示 new_ver
的值,那 很容易解决:
new_ver := $(shell ./app/gen_version.sh $(BUILD))
$(info $(new_ver))