1#* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2#*                                                                           *
3#*                  This file is part of the program and library             *
4#*         SCIP --- Solving Constraint Integer Programs                      *
5#*                                                                           *
6#*    Copyright (C) 2002-2021 Konrad-Zuse-Zentrum                            *
7#*                            fuer Informationstechnik Berlin                *
8#*                                                                           *
9#*  SCIP is distributed under the terms of the ZIB Academic License.         *
10#*                                                                           *
11#*  You should have received a copy of the ZIB Academic License              *
12#*  along with SCIP; see the file COPYING. If not email to scip@zib.de.      *
13#*                                                                           *
14#* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
15
16#@file    Makefile
17#@brief   Makefile for unit tests
18#@author  Felipe Serrano
19
20#-----------------------------------------------------------------------------
21# Probably nothing below here should be changed
22# TODO: use the $ORIGIN variable
23# NOTE: currently, compilation with SHARED=false is not supported.
24# One would need to add more flags (eg $(LDFLAGS)) when linking
25#-----------------------------------------------------------------------------
26
27UNITTESTSSRC	=	$(shell find src/ -name *.c)
28
29# remove unittests in src/bugs if BUGS is not true
30ifneq ($(BUGS),true)
31	UNITTESTSSRC 	:= $(filter-out $(shell find src/bugs/ -name *.c),$(UNITTESTSSRC))
32endif
33
34# removes `src/` prefix and file.c postfix, then sorts, which removes duplicates!
35TESTDIRS 	= $(sort $(dir $(patsubst src/%,%,$(UNITTESTSSRC))))
36#$(warning testdirs: $(TESTDIRS))
37
38#-----------------------------------------------------------------------------
39# paths
40#-----------------------------------------------------------------------------
41
42SCIPDIR		=	..
43
44#-----------------------------------------------------------------------------
45# SET OPTIONS FROM SCIP BINARY
46#-----------------------------------------------------------------------------
47
48ifneq ("$(wildcard $(SCIPDIR)/bin/scip)","")
49# put an @ at the end of each line of scip -v to use as a marker for sed
50SCIPVERSION		:=$(shell $(SCIPDIR)/bin/scip -v | sed -e 's/$$/@/')
51override ARCH		:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* ARCH=\([^@]*\).*/\1/')
52override COMP		:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* COMP=\([^@]*\).*/\1/')
53override EXPRINT	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* EXPRINT=\([^@]*\).*/\1/')
54override GAMS		:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* GAMS=\([^@]*\).*/\1/')
55override GMP		:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* GMP=\([^@]*\).*/\1/')
56override SYM		:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* SYM=\([^@]*\).*/\1/')
57override IPOPT		:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* IPOPT=\([^@]*\).*/\1/')
58override IPOPTOPT	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* IPOPTOPT=\([^@]*\).*/\1/')
59override LPS		:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* LPS=\([^@]*\).*/\1/')
60override LPSCHECK	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* LPSCHECK=\([^@]*\).*/\1/')
61override LPSOPT 	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* LPSOPT=\([^@]*\).*/\1/')
62override NOBLKBUFMEM	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* NOBLKBUFMEM=\([^@]*\).*/\1/')
63override NOBLKMEM	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* NOBLKMEM=\([^@]*\).*/\1/')
64override NOBUFMEM	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* NOBUFMEM=\([^@]*\).*/\1/')
65override OPT		:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* OPT=\([^@]*\).*/\1/')
66override OSTYPE		:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* OSTYPE=\([^@]*\).*/\1/')
67override PARASCIP	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* PARASCIP=\([^@]*\).*/\1/')
68override READLINE	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* READLINE=\([^@]*\).*/\1/')
69override SANITIZE	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* SANITIZE=\([^@]*\).*/\1/')
70override SHARED		:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* SHARED=\([^@]*\).*/\1/')
71override USRARFLAGS	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* USRARFLAGS=\([^@]*\).*/\1/')
72override USRCFLAGS	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* USRCFLAGS=\([^@]*\).*/\1/')
73override USRCXXFLAGS	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* USRCXXFLAGS=\([^@]*\).*/\1/')
74override USRFLAGS	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* USRFLAGS=\([^@]*\).*/\1/')
75override USRLDFLAGS	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* USRLDFLAGS=\([^@]*\).*/\1/')
76override USROFLAGS	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* USROFLAGS=\([^@]*\).*/\1/')
77override VERSION	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* VERSION=\([^@]*\).*/\1/')
78override ZIMPL		:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* ZIMPL=\([^@]*\).*/\1/')
79override ZIMPLOPT	:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* ZIMPLOPT=\([^@]*\).*/\1/')
80override ZLIB		:=$(shell echo "$(SCIPVERSION)" | sed -e 's/.* ZLIB=\([^@]*\).*/\1/')
81endif
82
83#-----------------------------------------------------------------------------
84# include default project Makefile from SCIP
85#-----------------------------------------------------------------------------
86
87include $(SCIPDIR)/make/make.project
88
89BASESUFFIX	=	.$(BASE).$(LPS)$(EXEEXTENSION)
90
91#-----------------------------------------------------------------------------
92# Functions
93#-----------------------------------------------------------------------------
94
95src2obj		=	$(patsubst $(SRCDIR)%,$(OBJDIR)%,$(1:.c=.o))
96#$(warning obj2src: src/cons/quadratic/quadratic.c -> \
97	$(call src2obj, src/cons/quadratic/quadratic.c))
98
99#-----------------------------------------------------------------------------
100# Unit test definitions
101#-----------------------------------------------------------------------------
102
103
104BINDIRS 	= 	$(addprefix $(BINDIR)/, $(TESTDIRS))
105#$(warning bindirs: $(BINDIRS))
106
107OBJDIRS 	= 	$(addprefix $(OBJDIR)/, $(TESTDIRS))
108#$(warning objdirs: $(OBJDIRS))
109
110# remove the .c from UNITTESTSSRC: src/lpi/bases, src/cons/quadratic/gauge, etc
111UNITTESTS 	= 	$(basename $(UNITTESTSSRC))
112#$(warning unittests: $(UNITTESTS))
113
114# build object files from source files: obj/O.linux.../cons/expr/free.o, etc
115UNITTESTSOBJ 	= 	$(call src2obj, $(UNITTESTSSRC))
116#$(warning unittestobj: $(UNITTESTSOBJ))
117
118# build dependency files from object files: obj/O.linux.../cons/expr/free.d, etc
119UNITTESTSDEP 	= 	$(UNITTESTSOBJ:.o=.d)
120#$(warning unittestdep: $(UNITTESTSDEP))
121
122# substitute src/ for $(OBJDIR) and append $(BASESUFFIX) to UNITTESTS: bin/cons/expr/free.linux..., etc
123UNITTESTSBIN 	= 	$(addsuffix $(BASESUFFIX), $(patsubst $(SRCDIR)%,$(BINDIR)%,$(UNITTESTS)))
124#$(warning unittestsbin: $(UNITTESTSBIN))
125
126UNITTESTSEXECS	=	$(addsuffix $(BASESUFFIX), $(UNITTESTS))
127
128#-----------------------------------------------------------------------------
129# Flags
130# filter out some flags to make criterion compile without warnings with gcc
131# and make the tests run with clang.
132# TODO: in newer version, check if we still need this
133#-----------------------------------------------------------------------------
134
135CFLAGS 		:=	$(filter-out -Wdeclaration-after-statement -Wstrict-prototypes, $(CFLAGS))
136ifeq ($(COMP), clang)
137CFLAGS 		:=	$(filter-out -Wcast-align, $(CFLAGS))
138endif
139CFLAGS 		+=	-std=c99
140# to find include/scip_test.h
141FLAGS 		+= 	-I.
142
143#-----------------------------------------------------------------------------
144# Criterion Framework
145#-----------------------------------------------------------------------------
146CR_INC		=	$(wildcard Criterion/include)
147CR_LIBDIR	=	$(wildcard Criterion/lib)
148CR_LIB		=	criterion
149
150#-----------------------------------------------------------------------------
151# Rules
152# Small remainder:
153# $@ refers to the target
154# $^ refers to all the dependencies
155# $< refers to all the first dependency
156# $? refers to the dependencies that are newer than the target
157# Newer dependencies are one reason why a rule is executed.
158#-----------------------------------------------------------------------------
159
160ifeq ($(VERBOSE),false)
161.SILENT:	$(UNITTESTSBIN) $(UNITTESTSOBJ)
162endif
163
164
165.PHONY: all
166all:            Criterion $(OBJDIR) $(OBJDIRS) $(BINDIRS) $(UNITTESTSBIN)
167		make ctestrunner
168		setarch `uname -m` -R ctest --output-on-failure
169
170.PHONY: lint
171lint:		$(UNITTESTSSRC)
172		-rm -f lint.out
173		$(SHELL) -ec 'for i in $^; \
174			do \
175			echo $$i; \
176			$(LINT) $(SCIPDIR)/lint/scip.lnt +os\(lint.out\) -u -zero \
177			$(FLAGS) -UNDEBUG -USCIP_WITH_READLINE -USCIP_ROUNDING_FE $$i; \
178			done'
179
180$(OBJDIR):
181		@echo "-> Creating $@ directory"
182		@-mkdir -p $@
183$(OBJDIRS):
184		@echo "-> Creating $@ directory"
185		@-mkdir -p $@
186$(BINDIRS):
187		@echo "-> Creating $@ directory"
188		@-mkdir -p $@
189
190# run the tests with address space layout randomization disabled, as this isn't
191# compatible with Criterions parametrized tests (https://github.com/Snaipe/Criterion/issues/208)
192.PHONY: test
193test:           $(UNITTESTSBIN)
194		make ctestrunner
195		setarch `uname -m` -R ctest --output-on-failure
196
197.PHONY: ctestrunner
198ctestrunner: 	$(UNITTESTSBIN)
199		@echo -e "#Automatic generated file\n" > "CTestTestfile.cmake"
200		@echo -e $(foreach bin,$(UNITTESTSBIN), \
201			"ADD_TEST($(shell echo $(bin:$(BASESUFFIX)=) | sed s/^bin/test/g | sed s/\\//_/g) $(bin))\n" >> "CTestTestfile.cmake")
202
203.PHONY: clean
204clean:
205		@echo "-> remove main object files"
206		$(foreach dir, $(OBJDIRS) $(OBJDIR), \
207			@-rm -f $(dir)/*.o $(dir)/*.d)
208		@echo "-> remove binaries"
209		$(foreach bin, $(UNITTESTSBIN), \
210			@-rm -f $(bin))
211
212.PHONY: tags
213tags:
214		rm -f TAGS; ctags -e src/*.c src/*.h $(SCIPDIR)/src/scip/*.c $(SCIPDIR)/src/scip/*.h;
215
216$(BINDIR)/%$(BASESUFFIX): $(OBJDIR)/%.o $(SCIPLIBFILE) $(LPILIBFILE) $(NLPILIBFILE) $(TPILIBFILE)
217		@echo "-> linking $@"
218		$(LINKCXX) $< $(LINKCXXSCIPALL) \
219		$(LINKCXX_l)$(TPILIB) \
220		$(addprefix $(LINKCXX_L),$(CR_LIBDIR)) \
221		$(LINKCXX_l)$(CR_LIB) \
222		$(LINKRPATH)$(realpath $(SCIPDIR)/lib/shared) \
223		$(addprefix $(LINKRPATH),$(realpath $(CR_LIBDIR))) \
224		$(SANITIZERFLAGS) \
225		$(LINKCXX_o)$@
226
227$(LPILIBFILE):
228		$(error $@ not available. SCIP must be compiled with OPT=$(OPT) SHARED=$(SHARED) LPS=$(LPS))
229$(SCIPLIBFILE):
230		$(error $@ not available. SCIP must be compiled with OPT=$(OPT) SHARED=$(SHARED))
231$(NLPILIBFILE):
232		$(error $@ not available. SCIP must be compiled with OPT=$(OPT) SHARED=$(SHARED) IPOPT=$(IPOPT))
233$(TPILIBFILE):
234		$(error $@ not available. SCIP must be compiled with OPT=$(OPT) SHARED=$(SHARED) TPI=$(TPI))
235
236-include	$(UNITTESTSDEP)
237
238$(OBJDIR)/%.o : $(SRCDIR)/%.c | $(OBJDIR) $(OBJDIRS) $(BINDIRS)
239		@echo "-> compiling $@"
240		$(CC) $(addprefix -I,$(CR_INC)) $(FLAGS) $(OFLAGS) $(BINOFLAGS) $(CFLAGS) $(DFLAGS) -c $< $(CC_o)$@
241
242$(OBJDIR)/%.o:	%.cpp
243		@echo "-> compiling $@"
244		$(CXX) $(addprefix -I,$(CR_INC)) $(FLAGS) $(OFLAGS) $(BINOFLAGS) $(CXXFLAGS) $(DFLAGS) -c $< $(CXX_o)$@
245
246Criterion:
247	@echo -n "Criterion not found, downloading and building it in"
248	@for (( count=3; $$count ; count-- )) do echo -n " $$count" ; sleep 1 ; done ; echo
249	git clone --depth 1 -b v2.3.3 https://github.com/Snaipe/Criterion
250	cd Criterion; \
251	mkdir build; \
252	cd build; \
253	cmake .. -DCMAKE_INSTALL_PREFIX=..; \
254	make; \
255	make install
256
257#---- EOF --------------------------------------------------------------------
258