有没有办法让软件构建/编译更快?我们有一个构建树c,c ++使用makefile,接近2小时进行新构建.我遇到过几个商业解决方案,比如ElectricAccelerator,Sparkbuild,有没有相应的开源资源?
我有以下问题:
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG build/liblcthw.a tests/list_tests.c -o tests/list_tests
/tmp/ccpvGjZp.o: In function `test_create':
~/lcthw/tests/list_tests.c:12: undefined reference to `List_create'
collect2: ld returned 1 exit status
make: *** [tests/list_tests] Error 1
Run Code Online (Sandbox Code Playgroud)
但
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG tests/list_tests.c build/liblcthw.a -o tests/list_tests
Run Code Online (Sandbox Code Playgroud)
运行得很好,nm显示预期的内容,测试运行,每个人都很开心,等等.
我搜索了SO并找到了很多答案(例如链接器命令 - GCC),所以很明显链接器的工作原理应该如此.那么,我应该如何修改我的makefile以遵循命令呢?
到目前为止,这是Makefile:
CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS)
LIBS=$(OPTLIBS)
PREFIX?=/usr/local
BUILD=build
SOURCES=$(wildcard src/**/*.c src/*.c)
OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,$(TEST_SRC))
TARGET=$(BUILD)/liblcthw.a
TARGET_LINK=lcthw
SO_TARGET=$(patsubst %.a,%.so,$(TARGET))
#The …Run Code Online (Sandbox Code Playgroud) $(error ...)如果不满足某些先决条件,我想用来中止我的制作过程.在fails_to_work失败时,目标应该退出test -d /foobar.
BAD.mk
all: this_works fails_to_work
this_works:
@echo echo works...
@test -d ~ || echo ~ is not a directory
@test -d /foobar || echo /foobar is not a directory
fails_to_work:
@echo error does not work...
@test -d ~ || $(error ~ is not a directory)
@test -d /foobar || $(error /foobar is not a directory)
Run Code Online (Sandbox Code Playgroud)
$ make -f BAD.mk
echo works...
/foobar is not a directory
BAD.mk:9: *** ~ is not a …Run Code Online (Sandbox Code Playgroud) 似乎GNU make解释的basename函数与bash的basename不同.前者剥去后缀,而后者也剥离路径.如何在makefile中获取文件夹的基本名称?
另外,为什么他们改变了呢?(我花了20分钟才找到错误的来源)
我正在使用GNU Make来构建一个很多人都会使用的C/C++项目.makefile尝试通用,因为此项目中有许多可选文件,每个用户通过MATLAB接口选择这些文件,然后通过命令行参数提供给makefile(make target OPTS ='XYZ'等...).
当我使用makefile时,它正确识别正确的对象依赖项,然后继续查找这些对象的源先决条件并构建它们.但是,每次尝试执行对象规则时,我都会在gcc调用之后收到错误消息"Abort trap:6".
Makefile如下
vpath %.c $(PATH) $(OBJ_DIR)
# Pick compilers
CC1=g++
CC2=gcc
LNK=g++
# Assign variables for c/cpp implicit rules
CXXFLAGS= $(CCFLAGS) $(DEFINES) $(INCLUDES)
CFLAGS = $(CCFLAGS) $(DEFINES) $(INCLUDES)
# Assign various user-defined values
OUTPUT = -o $(USER_LIB)
C_OBJECTS = $(patsubst %.c,$(OBJ_DIR)/%.o,$(C_SOURCES))
CPP_OBJECTS = $(patsubst %.cpp,$(OBJ_DIR)/%.o,$(CPP_SOURCES))
OBJECTS = $(C_OBJECTS) $(CPP_OBJECTS) $(SIM_OBJECTS)
# User Library Dependencies and Compilation Rules
$(USER_LIB): $(OBJECTS)
$(LNK) $(LINKERFLAGS) $(CCFLAGS) $(DEFINES) $(INCLUDES) $(OUTPUT) $(OBJECTS)
$(OBJ_DIR)/%.o: %.c
$(CC2) $(CFLAGS) -c -o $@ $< …Run Code Online (Sandbox Code Playgroud) 在gnu-make进程的后期阶段,gmake发送了一个类似于的命令:
gcc -static foo.so.0 bar.o bizz.o buzz.o -pthreads -lrt
Run Code Online (Sandbox Code Playgroud)
在那个命令中,-lrt是什么意思?
我注意到在Gnu Make中的隐式规则是变量$(TARGET_ARCH),例如:
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
LINK.o = $(CC) $(LDFLAGS) $(TARGET_ARCH)
Run Code Online (Sandbox Code Playgroud)
我认为交叉编译需要这个变量,但我没有在Gnu Make文档中找到任何关于它的信息.
以下是关于辅助扩展的GNU Make手册部分的示例(略微简化):
foo_SRCS := bar.c baz.c
.SECONDEXPANSION:
# $$@ expands to the target ("foo" in this case)
foo: $$(patsubst %.c,%.o,$$($$@_SRCS))
Run Code Online (Sandbox Code Playgroud)
这很好用; 它构建bar.o和baz.o:
cc -c -o bar.o bar.c
cc -c -o baz.o baz.c
Run Code Online (Sandbox Code Playgroud)
但是,如果我只略微调整这个例子,patsubst停止工作:
all: foo.a
foo_SRCS := bar.c baz.c
.SECONDEXPANSION:
# $$* expands to the stem of the match ("foo" in this case).
%.a: $$(patsubst %.c,%.o,$$($$*_SRCS))
ar rcs $@ $^
Run Code Online (Sandbox Code Playgroud)
它不再建造bar.o和baz.o,而是使用*.c直接文件作为先决条件!
ar rcs foo.a …Run Code Online (Sandbox Code Playgroud) 我在make文件中定义了一个列表,用户应该设置一个我需要在此列表中找到的环境变量.有没有办法使用gnu make来做到这一点?在开始构建任何目标之前,我想在任何配方之外执行此操作.这是一个QA检查,以确保用户设置env.变量到范围/列表中的值.
在终端上:
setenv ENV_PARAM x
Run Code Online (Sandbox Code Playgroud)
在Makefile中:
PARAMS := a b c
if ${ENV_PARAM} exists in $(PARAMS)
true
else
false
endif
Run Code Online (Sandbox Code Playgroud)
@MadScientist的答案有效.有没有办法用foreach循环包装if块来测试多个参数?
KEYS := PARAMS FACTORS
PARAMS := a b c
FACTORS := x y z
foreach v in ($(KEYS)) {
ifneq ($(filter $(ENV_$(v)),$(v)),)
$(info $(ENV_$(v)) exists in $(v))
else
$(info $(ENV_$(v)) does not exist in $(v))
endif
}
Run Code Online (Sandbox Code Playgroud) 我的makefile文件中包含以下内容。其为GNUmakefile,因此支持其他制造功能:
# Undefined Behavior Sanitzier (Clang and G++)
ifeq ($(findstring ubsan,$(MAKECMDGOALS)),ubsan)
CXXFLAGS += -fsanitize=undefined
MAKECMDGOALS := $(subst ubsan,,$(MAKECMDGOALS))
endif # UBsan
Run Code Online (Sandbox Code Playgroud)
运行它会导致:
make ubsan
make: *** No rule to make target 'ubsan'. Stop.
Run Code Online (Sandbox Code Playgroud)
我知道代码路径正在执行中(通过在块中引入错误)。如何从命令目标中删除目标?