-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathMakefile
More file actions
316 lines (265 loc) · 9.79 KB
/
Makefile
File metadata and controls
316 lines (265 loc) · 9.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# --- Project config ----------------------------------------------------------
APP ?= AMDAT
SRC_DIR := src
BUILD_DIR := build
# Feature toggles
MODE ?= release # debug | release
OMP ?= 1 # 1 enables OpenMP
# Normalize MODE and OMP to avoid trailing-space bugs
MODE := $(strip $(MODE))
OMP := $(strip $(OMP))
# Toolchains
CXX ?= g++
CC ?= gcc
STD ?= c++17
WARN := -Wall -Wextra -Wshadow -Wconversion -Wpedantic
# Wavevector paths
WV3D ?= $(CURDIR)/src/qvectors/qvectors3d/qvector
WV2D ?= $(CURDIR)/src/qvectors/qvectors2d/qvector
WV1D ?= $(CURDIR)/src/qvectors/qvectors1d/qvector
# Wavevector bootstrap
WV_STAMP := $(SRC_DIR)/qvectors/.ready
# Add version.h for automated version info at build time
VERSION_H := src/generated/version.h
# Try to get a friendly describe string; ignore errors if not a repo
GIT_DESCRIBE := $(shell git describe --tags --dirty --always 2>/dev/null)
GIT_COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null)
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
# Extract SemVer from tag if present (v1.2.3 → 1.2.3)
# Fallback: read VERSION, else default
ifeq ($(strip $(GIT_DESCRIBE)),)
AMDAT_SEMVER := $(strip $(shell [ -f VERSION ] && cat VERSION))
ifeq ($(strip $(AMDAT_SEMVER)),)
AMDAT_SEMVER := 0.0.0+archive
endif
else
# pull the first thing that looks like vX.Y.Z or X.Y.Z
AMDAT_SEMVER := $(shell echo "$(GIT_DESCRIBE)" | sed -E 's/.*(v?[0-9]+\.[0-9]+\.[0-9]+).*/\1/' | sed 's/^v//')
endif
# Allow packagers to override from environment: AMDAT_SEMVER=1.0.0+pkg make
ifneq ($(origin AMDAT_SEMVER),file)
AMDAT_SEMVER := $(AMDAT_SEMVER)
endif
BUILD_DATE := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
# --- Flags -------------------------------------------------------------------
CPPFLAGS := -MMD -MP -I./src \
-I./src/generated \
-I./third_party/voro++-0.4.6/src \
-L./third_party/voro++-0.4.6/src \
-I./third_party/xdrfile-1.1b/src \
-DWV3D=\"$(WV3D)\" \
-DWV2D=\"$(WV2D)\" \
-DWV1D=\"$(WV1D)\"
CXXFLAGS := -std=$(STD) $(WARN)
CFLAGS ?= -O3 -DNDEBUG
LDFLAGS :=
LDLIBS := -lvoro++ -L./third_party/voro++-0.4.6/src
FFTW_ROOT ?=
# --- try pkg-config first ---
PKGCONF ?= pkg-config
ifeq ($(shell which $(PKGCONF) >/dev/null 2>&1 && echo yes),yes)
ifeq ($(shell $(PKGCONF) --exists fftw3 && echo yes),yes)
CPPFLAGS += $(shell $(PKGCONF) --cflags fftw3)
LDLIBS += $(shell $(PKGCONF) --libs fftw3)
endif
endif
# --- fallback: user-specified prefix ---
ifneq ($(FFTW_ROOT),)
CPPFLAGS += -I$(FFTW_ROOT)/include
LDFLAGS += -L$(FFTW_ROOT)/lib
LDLIBS += -lfftw3
endif
ifeq ($(OMP),1)
CXXFLAGS += -fopenmp
LDLIBS += -fopenmp
endif
# Build profile
ifeq ($(MODE),debug)
CXXFLAGS += -O0 -g3
else ifeq ($(MODE),release)
CXXFLAGS += -O3 -DNDEBUG
else
$(error Unknown MODE '$(MODE)'; use MODE=debug or MODE=release)
endif
# Optional: ccache if installed
ifneq ($(shell command -v ccache 2>/dev/null),)
CXX := ccache $(CXX)
endif
# --- xdrfile (GROMACS XTC/TRR) integration ----------------------------------
# The bundled C library lives at ./third_party/xdrfile-1.1b
XDR_DIR ?= third_party/xdrfile-1.1b
XDR_INC = $(XDR_DIR)/include
XDR_SRC_DIR = $(XDR_DIR)/src
# Make sure C and C++ compiles can find headers
CPPFLAGS += -I./$(XDR_INC) -I./$(XDR_DIR)
XDR_CFLAGS := -I./$(XDR_INC) -I./$(XDR_DIR) $(CFLAGS)
# C sources to build from xdrfile
XDR_CSRCS := $(XDR_SRC_DIR)/xdrfile.c \
$(XDR_SRC_DIR)/xdrfile_xtc.c \
$(XDR_SRC_DIR)/xdrfile_trr.c
XDR_OBJS := $(patsubst $(XDR_SRC_DIR)/%.c,$(BUILD_DIR)/xdr/%.o,$(XDR_CSRCS))
# Some distros require -lm for math symbols used by xdrfile
LDLIBS += -lm
# Ensure dir exists
$(shell mkdir -p $(BUILD_DIR)/xdr)
# --- Source discovery (flat, only src/*.cpp) ---------------------------------
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
# Exclude specific sources
EXCLUDE_SRCS := src/time_correlation_function.cpp \
src/spherical_wave_vectors.cpp \
src/spacial_decomposition.cpp
SRCS := $(filter-out $(EXCLUDE_SRCS),$(SRCS))
# Map to objects in build/
OBJS := $(patsubst $(SRC_DIR)/%.cpp,$(BUILD_DIR)/%.o,$(SRCS))
DEPS := $(OBJS:.o=.d)
# Ensure build dirs exist
$(shell mkdir -p $(BUILD_DIR))
# --- Targets -----------------------------------------------------------------
.PHONY: all clean distclean rebuild format lint help
all: $(APP)
$(VERSION_H):
@mkdir -p $(dir $@)
@{ \
echo '#pragma once'; \
echo 'namespace amdat::build {'; \
echo 'inline constexpr const char* NAME="AMDAT";'; \
echo 'inline constexpr const char* SEMVER="$(AMDAT_SEMVER)";'; \
echo 'inline constexpr const char* GIT_DESCRIBE="$(GIT_DESCRIBE)";'; \
echo 'inline constexpr const char* GIT_COMMIT="$(GIT_COMMIT)";'; \
echo 'inline constexpr const char* GIT_BRANCH="$(GIT_BRANCH)";'; \
echo 'inline constexpr const char* BUILD_DATE="$(BUILD_DATE)";'; \
echo 'inline constexpr const char* COMPILER='; \
echo '#if defined(__clang__)'; \
echo ' "clang " __clang_version__;'; \
echo '#elif defined(__GNUC__)'; \
echo ' "gcc " __VERSION__;'; \
echo '#elif defined(_MSC_VER)'; \
echo ' "MSVC";'; \
echo '#else'; \
echo ' "unknown";'; \
echo '#endif'; \
echo 'inline constexpr bool OPENMP='; \
echo '#ifdef _OPENMP'; \
echo 'true;'; \
echo '#else'; \
echo 'false;'; \
echo '#endif'; \
echo '}'; \
} > $@
.PHONY: voro
voro:
$(MAKE) -C third_party/voro++-0.4.6 \
CC="$(CC)" CXX="$(CXX)"
.PHONY: clean_voro
clean_voro:
$(MAKE) -C third_party/voro++-0.4.6 clean
.PHONY: clean_qvectors
clean_qvectors:
@$(RM) -rf $(SRC_DIR)/qvectors/.ready
@$(MAKE) -C $(SRC_DIR)/qvectors distclean
.PHONY: qvectors
qvectors: $(WV_STAMP)
$(WV_STAMP):
@$(MAKE) -C $(SRC_DIR)/qvectors
# Final link: include xdrfile objects as well
$(APP): $(OBJS) $(XDR_OBJS) $(VORO_OBJS) | qvectors voro
@echo " LINK $@"
$(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS)
# Compile C++: strictly src/<file>.cpp → build/<file>.o
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp | $(VERSION_H)
@echo " CXX $<"
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
# Compile C from xdrfile: third_party/xdrfile-1.1b/src/*.c → build/xdr/*.o
$(BUILD_DIR)/xdr/%.o: $(XDR_SRC_DIR)/%.c
@echo " CC $<"
$(CC) $(XDR_CFLAGS) -c $< -o $@
## Compile voro++: third_party/voro++-0.4.6/src/*.cc → build/voro/*.o (isolated includes)
#$(BUILD_DIR)/voro/%.o: $(VORO_DIR)/%.cc
# @echo " CXX $< (voro++)"
# $(CXX) $(VORO_CPPFLAGS) $(CXXFLAGS) -c $< -o $@
#
# Include auto-generated header dependencies (for C++ objects)
-include $(DEPS)
clean: clean_voro
@echo " CLEAN objects"
@rm -rf $(BUILD_DIR)/*
distclean: clean clean_qvectors
@echo " CLEAN binary"
@rm -f $(APP)
rebuild: distclean all
# Code quality helpers (optional)
format:
@command -v clang-format >/dev/null || { echo "clang-format not found"; exit 1; }
@echo " FORMAT src/**/*.h,*.hpp,*.cpp"
@find src -type f \( -name '*.hpp' -o -name '*.h' -o -name '*.cpp' \) -print0 | xargs -0 clang-format -i
lint:
@command -v clang-tidy >/dev/null || { echo "clang-tidy not found"; exit 1; }
@echo " LINT (clang-tidy)"
@clang-tidy -p . $(SRCS)
help:
@echo "Targets:"
@echo " all (default) Build $(APP) [MODE=$(MODE) OMP=$(OMP)]"
@echo " clean Remove objects only"
@echo " distclean Remove objects and binary"
@echo " rebuild Full clean + build"
@echo " format Run clang-format (if installed)"
@echo " lint Run clang-tidy (if installed)"
@echo
@echo "Examples:"
@echo " make MODE=debug"
@echo " make MODE=release OMP=0"
# --- Conda helpers (do not require 'conda activate') -------------------------
CONDA ?= conda
ENV_NAME ?= amdat
# Prefer an exact lock if present, else fall back to environment.yml
ENV_SPEC ?= $(if $(wildcard conda-linux-64.txt),conda-linux-64.txt,environment.yml)
ENV_STAMP := .env/conda.ready
# Create/update the Conda environment
.PHONY: conda-setup
conda-setup: $(ENV_STAMP)
$(ENV_STAMP):
@echo ">> Creating conda env '$(ENV_NAME)' from $(ENV_SPEC)"
@mkdir -p .env
@if [ "$(ENV_SPEC)" = "conda-linux-64.txt" ]; then \
$(CONDA) create -y -n $(ENV_NAME) --file $(ENV_SPEC); \
else \
$(CONDA) env create -n $(ENV_NAME) -f $(ENV_SPEC) || $(CONDA) env update -n $(ENV_NAME) -f $(ENV_SPEC); \
fi
@touch $@
# Build *inside* the Conda env, ensuring:
# - we use conda-forge compilers if present
# - pkg-config sees FFTW from the env
# - parallel build matches CPU count on the node
.PHONY: conda
conda: $(ENV_STAMP)
@$(CONDA) run -n $(ENV_NAME) bash -lc '\
set -euo pipefail; \
: "$${CONDA_PREFIX:?conda run did not set CONDA_PREFIX}"; \
export PKG_CONFIG_PATH="$$CONDA_PREFIX/lib/pkgconfig:$${PKG_CONFIG_PATH:-}"; \
# Prefer conda-forge triplet compilers if available; otherwise keep Makefile defaults \
if command -v x86_64-conda-linux-gnu-g++ >/dev/null 2>&1; then \
MAKE_CXX="CXX=x86_64-conda-linux-gnu-g++"; \
MAKE_CC="CC=x86_64-conda-linux-gnu-gcc"; \
else \
MAKE_CXX=""; MAKE_CC=""; \
fi; \
echo ">> Using $$MAKE_CC $$MAKE_CXX"; \
export CPATH="$$CONDA_PREFIX/include:$${CPATH:-}"; \
export LIBRARY_PATH="$$CONDA_PREFIX/lib:$${LIBRARY_PATH:-}"; \
echo ">> pkg-config: $(which pkg-config || true)"; \
echo ">> fftw cflags: $$(pkg-config --cflags fftw3 || true)"; \
echo ">> fftw libs: $$(pkg-config --libs fftw3 || true)"; \
$(MAKE) $$MAKE_CC $$MAKE_CXX MODE=$(MODE) OMP=$(OMP) FFTW_ROOT="$$CONDA_PREFIX" \
'
# Optional: interactive shell in the env (handy for debugging)
.PHONY: conda-shell
conda-shell: $(ENV_STAMP)
@$(CONDA) run -n $(ENV_NAME) bash
# Clean just your build outputs (keeps the env)
.PHONY: conda-clean
conda-clean:
@$(RM) -rf $(BUILD_DIR)/*
# Nukes the env stamp (does NOT delete the conda env itself)
.PHONY: conda-unstamp
conda-unstamp:
@$(RM) -f $(ENV_STAMP)