1# Generic Makefile for GEMMA
2#
3# Supported platforms
4#
5#       Unix / Linux               LNX (default)
6#       Mac                        OSX
7#       GNU Guix                   GUIX (set to profile)
8#
9# Compilation options
10#       static compilation         FORCE_STATIC
11#
12# Examples:
13#
14#    Make GEMMA on Linux without OPENBLAS support:
15#
16#      make WITH_OPENBLAS=
17#
18#    Disable debug info and checks (release mode is slightly faster)
19#
20#      make debug
21#
22#    Force static compilation
23#
24#      make static
25#
26#    Run tests with
27#
28#      make check
29#
30#    Run quick (development) tests with
31#
32#      make fast-check
33#
34#    Run full (lengthy) tests with
35#
36#      make check-all
37#
38#    To compile with CLANG
39#
40#      make CXX=clang++
41#
42#    See also the INSTALL.md document in the source tree at
43#
44#      https://github.com/genetics-statistics/GEMMA/blob/master/INSTALL.md
45
46GEMMA_VERSION = $(shell cat ./VERSION)
47
48# Set this variable to either LNX or OSX
49ifeq ($(OS),Windows_NT)
50  SYS = WIN
51  VGEN = scripts/gen_version_info.cmd
52else
53  UNAME_S := $(shell uname -s)
54  ifeq ($(UNAME_S),Darwin)
55    SYS = OSX
56  else
57    SYS = LNX # default to linux
58  endif
59  VGEN = scripts/gen_version_info.sh
60endif
61
62# Leave blank after "=" to disable; put "= 1" to enable
63DIST_NAME              = gemma-$(GEMMA_VERSION)
64DEBUG                  = 1                # DEBUG mode, set DEBUG=0 for a release
65PROFILING              =                  # Add profiling info
66SHOW_COMPILER_WARNINGS =
67WITH_OPENBLAS          = 1                # Without OpenBlas uses LAPACK
68WITH_ATLAS             =                  # In place of OpenBlas(?)
69WITH_LAPACK            =                  # Force linking LAPACK (if OpenBlas lacks it)
70WITH_GSLCBLAS          =                  # Force linking gslcblas (if OpenBlas lacks it)
71WITH_GFORTRAN          =                  # Add -lgfortran (if OpenBlas does not pull it in)
72OPENBLAS_LEGACY        =                  # Using older OpenBlas
73FORCE_STATIC           =                  # Static linking of libraries
74GCC_FLAGS              = -DHAVE_INLINE -pthread -Wall -std=gnu++11 # extra flags -Wl,--allow-multiple-definition
75
76GSL_INCLUDE_PATH =
77ifeq ($(SYS), WIN)
78  GSL_INCLUDE_PATH = -isystemc:/MinGW/include -LC:/MinGW/lib
79  OPENBLAS_INCLUDE_PATH = ../OpenBLAS-v0.2.19-Win64-int32/include -L../OpenBLAS-v0.2.19-Win64-int32/lib
80else
81  OPENBLAS_INCLUDE_PATH = /usr/local/opt/openblas/include
82  ifndef GUIX
83    ifdef GUIX_ENVIRONMENT
84      GUIX=$(GUIX_ENVIRONMENT)
85    endif
86  endif
87  ifdef GUIX
88    # Effectively disable paths for GNU Guix
89    OPENBLAS_INCLUDE_PATH = .
90    # RPATH = -Xlinker --rpath=$(GUIX)/lib
91    ifdef FORCE_STATIC
92      LIBS = -L$(GUIX)/lib
93    endif
94    GUIX_PROFILE =$(realpath $(GUIX))
95  endif
96endif
97
98# --------------------------------------------------------------------
99# Edit below this line with caution
100# --------------------------------------------------------------------
101
102BIN_DIR  = ./bin
103SRC_DIR  = ./src
104TEST_SRC_DIR  = ./test/src
105
106ifdef CXX # CXX defined in environment
107  CPP = $(CXX)
108  CC = $(CXX)
109else
110  CPP = g++
111endif
112
113ifeq ($(CPP), clang++)
114  GCC_FLAGS=-std=c++11 -isystem$(OPENBLAS_INCLUDE_PATH)
115  ifdef GUIX
116    CPPFLAGS += -I$(GUIX)/include/c++ -I$(GUIX)/include/c++/x86_64-unknown-linux-gnu
117  endif
118endif
119
120ifdef WITH_OPENBLAS
121  OPENBLAS=1
122  # WITH_LAPACK =  # OPENBLAS usually includes LAPACK
123  CPPFLAGS += -DOPENBLAS -isystem$(OPENBLAS_INCLUDE_PATH)
124  ifdef OPENBLAS_LEGACY
125    # Legacy version (mostly for Travis-CI)
126    CPPFLAGS += -DOPENBLAS_LEGACY
127  endif
128else
129  ifdef WITH_ATLAS
130    CPPFLAGS += -DUSE_BLAS=atlas
131  endif
132endif
133
134ifneq ($(CXX), clang++)
135  # Clang does not like these switches
136  debug check fast-check: CPPFLAGS += -Og -Wfatal-errors
137endif
138
139debug check fast-check: CPPFLAGS += -g $(GCC_FLAGS) $(GSL_INCLUDE_PATH) -Icontrib/catch-1.9.7 -Isrc
140
141profile: CPPFLAGS += -pg
142
143release: CPPFLAGS += -DNDEBUG -O3 $(GCC_FLAGS) $(GSL_INCLUDE_PATH) -Icontrib/catch-1.9.7 -Isrc
144
145static: CPPFLAGS += -DNDEBUG -O3 $(GCC_FLAGS) $(GSL_INCLUDE_PATH) -Icontrib/catch-1.9.7 -Isrc
146
147
148ifeq ($(SYS), WIN)
149  CPPFLAGS += -Duint="unsigned int" -D__CRT__NO_INLINE -D__STRING="__STRINGIFY" -DWINDOWS -DWITH_GSLCBLAS=1
150endif
151
152ifdef SHOW_COMPILER_WARNINGS
153  CPPFLAGS += -Wall
154endif
155
156static: CPPFLAGS += -static
157
158LIBS += -lgsl -lz
159ifdef WITH_OPENBLAS
160  LIBS += -lopenblas
161  ifeq ($(SYS), OSX)
162    ifdef WITH_OPENBLAS
163      LIBS += -Wl,-L/usr/local/opt/openblas/lib
164    endif
165  endif
166else
167  LIBS += -latlas -lcblas -llapack -lblas
168endif
169ifdef WITH_GSLCBLAS
170  LIBS += -lgslcblas
171endif
172ifdef WITH_GFORTRAN
173  LIBS += -lgfortran -lquadmath
174endif
175
176.PHONY: all test
177
178OUTPUT = $(BIN_DIR)/gemma
179
180# Detailed libary paths, D for dynamic and S for static
181
182ifdef WITH_LAPACK
183  LIBS += -llapack
184endif
185LIBS_OSX_D_LAPACK = -framework Accelerate
186
187ifdef WITH_LAPACK
188  ifeq ($(SYS), OSX)
189    LIBS += $(LIBS_OSX_D_LAPACK)
190    ifdef WITH_OPENBLAS
191      LIBS += -Wl,-L/usr/local/opt/openblas/lib
192    endif
193  endif
194endif
195
196HDR          = $(wildcard src/*.h) ./src/version.h
197SOURCES      = $(wildcard src/*.cpp)
198
199# all
200OBJS = $(SOURCES:.cpp=.o)
201
202all: release
203
204release: $(OUTPUT)
205
206static: $(OUTPUT)
207
208debug: $(OUTPUT)
209
210./src/version.h: ./VERSION
211	$(shell bash $(VGEN) $(GUIX_PROFILE) > src/version.h)
212
213$(OUTPUT): $(OBJS)
214	$(CPP) $(CPPFLAGS) $(OBJS) $(LIBS) -o $(OUTPUT)
215
216$(OBJS): $(HDR)
217
218.SUFFIXES : .cpp .c .o $(SUFFIXES)
219
220./bin/unittests-gemma: contrib/catch-1.9.7/catch.hpp $(TEST_SRC_DIR)/unittests-main.o $(TEST_SRC_DIR)/unittests-math.o $(OBJS)
221	$(CPP) $(CPPFLAGS) $(TEST_SRC_DIR)/unittests-main.o  $(TEST_SRC_DIR)/unittests-math.o $(filter-out src/main.o, $(OBJS)) $(LIBS) -o ./bin/unittests-gemma
222
223unittests: all ./bin/unittests-gemma
224	./bin/unittests-gemma
225
226fast-check: all unittests
227	rm -vf test/output/*
228	cd test && ./dev_test_suite.sh | tee ../dev_test.log
229	grep -q 'success rate: 100%' dev_test.log
230
231slow-check: all
232	rm -vf test/output/*
233	cd test && ./test_suite.sh | tee ../test.log
234	grep -q 'success rate: 100%' test.log
235
236lengthy-check: all
237	rm -vf test/output/*
238	cd test && ./lengthy_test_suite.sh | tee ../lengthy_test.log
239	grep -q 'success rate: 100%' lengthy_test.log
240
241check: fast-check slow-check
242
243check-all: check lengthy-check
244
245clean:
246	rm -vf $(SRC_DIR)/*.o
247	rm -vf $(SRC_DIR)/*~
248	rm -vf $(TEST_SRC_DIR)/*.o
249	rm -vf $(OUTPUT)
250	rm -vf ./bin/unittests-gemma
251
252DIST_COMMON = *.md LICENSE VERSION Makefile
253DIST_SUBDIRS = src doc example bin
254
255tar: version all
256	@echo "Creating $(DIST_NAME)"
257	mkdir -p ./$(DIST_NAME)
258	cp $(DIST_COMMON) ./$(DIST_NAME)/
259	cp -r $(DIST_SUBDIRS) ./$(DIST_NAME)/
260	tar cvzf $(DIST_NAME).tar.gz ./$(DIST_NAME)/
261	rm -r ./$(DIST_NAME)
262