-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild_lib.sh
More file actions
executable file
·177 lines (152 loc) · 5.96 KB
/
Copy pathbuild_lib.sh
File metadata and controls
executable file
·177 lines (152 loc) · 5.96 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
#!/usr/bin/env bash
# Build helper for CMake-based C++ projects (Linux)
# - Created Jan 2024; updated Aug 2025
# - Uses GNU getopt for long options
# - Generator-agnostic build via `cmake --build`
set -Eeuo pipefail
IFS=$'\n\t' # TODO what is this?
# --- defaults ---
buildpath="build"
jobs="${JOBS:-$(command -v nproc >/dev/null 2>&1 && nproc || echo 4)}"
rebuild_only=false
build_type="relwithdebinfo" # debug|release|relwithdebinfo|minsizerel
run_tests=true
CXX_FLAGS=""
python_wrap=false
matlab_wrap=false
install=false
use_ninja=false
no_optim=false
clean_first=false
# Helper function to print instructions
usage() {
cat <<'USAGE'
Usage: build_cpp.sh [OPTIONS]
Options:
-B, --buildpath <dir> Build directory (default: ./build)
-j, --jobs <N> Parallel build jobs (default: $(nproc or 4))
-r, --rebuild-only Skip CMake configure; build existing tree only
-t, --type|--type-build <t> Build type: debug|release|relwithdebinfo|minsizerel
-c, --checks Run tests (on by default). Alias of --run-tests
--skip-tests Do not run tests
-f, --flagsCXX <flags> Extra C++ flags (quoted). Appends warnings for
Debug/RelWithDebInfo/Release
-p, --python-wrap Enable Python wrapper in CMake (-DBUILD_PYTHON_WRAPPER=ON)
-m, --matlab-wrap Enable MATLAB wrapper in CMake (-DBUILD_MATLAB_WRAPPER=ON)
-i, --install Run "install" target after tests
-N, --ninja-build Use Ninja generator (requires `ninja`)
-n, --no-optim Set -DNO_OPTIMIZATION=ON in the CMake cache
--clean Delete build dir before configuring
-h, --help Show this help and exit
Examples:
# Configure + build (RelWithDebInfo) into ./build
./build_cpp.sh
# Debug build with warnings, 8 jobs, and Ninja
./build_cpp.sh -t debug -j 8 -N
# Custom build dir and flags, run tests then install
./build_cpp.sh -B out/release -t release -f "-march=native" -i
Notes:
* Short options with arguments use a separate value: "-B build", "-j 8".
* This script requires GNU getopt (standard on Debian/Ubuntu).
USAGE
}
# Auxiliary functions
die() { echo -e "\e[31mError:\e[0m $*" >&2; echo; usage; exit 2; } # Stop execution due to error
info() { echo -e "\e[34m[INFO]\e[0m $*"; } # Print info
trap 'echo -e "\e[31mBuild failed (line $LINENO).\e[0m"' ERR # Exit condition
# --- argument parsing (GNU getopt) ---
if ! command -v getopt > /dev/null 2>&1; then
die "GNU getopt is required. On macOS: brew install gnu-getopt and adjust PATH."
fi
OPTIONS=B:j:rt:c:f:pmhNni
LONGOPTIONS=buildpath:,jobs:,rebuild-only,type:,type-build:,checks,flagsCXX:,python-wrap,matlab-wrap,help,ninja-build,no-optim,skip-tests,clean,install
PARSED=$(getopt -o "$OPTIONS" -l "$LONGOPTIONS" -- "$@") || { usage; exit 2; }
eval set -- "$PARSED"
while true; do
case "$1" in
-B|--buildpath) buildpath="$2"; shift 2 ;;
-j|--jobs) jobs="$2"; shift 2 ;;
-r|--rebuild-only) rebuild_only=true; shift ;;
-t|--type|--type-build) build_type="$2"; shift 2 ;;
-c|--checks) run_tests=true; shift ;;
--skip-tests|--no-checks) run_tests=false; shift ;;
-f|--flagsCXX) CXX_FLAGS="$2"; shift 2 ;;
-p|--python-wrap) python_wrap=true; shift ;;
-m|--matlab-wrap) matlab_wrap=true; shift ;;
-i|--install) install=true; shift ;;
-N|--ninja-build) use_ninja=true; shift ;;
-n|--no-optim) no_optim=true; shift ;;
--clean) clean_first=true; shift ;;
-h|--help) usage; exit 0 ;;
--) shift; break ;;
*) die "Unknown option: $1" ;;
esac
done
# --- normalize & validate build type ---
bt="${build_type,,}"
case "$bt" in
debug) cmake_bt="Debug" ;;
release) cmake_bt="Release" ;;
relwithdebinfo) cmake_bt="RelWithDebInfo" ;;
minsizerel) cmake_bt="MinSizeRel" ;;
*) die "Invalid build type: $build_type" ;;
esac
# For common types, enforce warnings unless user already provided them
if [[ "$bt" =~ ^(debug|relwithdebinfo|release)$ ]]; then
CXX_FLAGS="${CXX_FLAGS:+$CXX_FLAGS }-Wall -Wextra -Wpedantic"
fi
# Enforce tests for Release
if [[ "$cmake_bt" == "Release" ]]; then
run_tests=true
fi
# Pre-build checks
command -v cmake >/dev/null 2>&1 || die "cmake not found"
if [[ "$use_ninja" == true ]]; then
command -v ninja >/dev/null 2>&1 || die "Requested Ninja but 'ninja' not found"
fi
# Print info
info "Buildpath : $buildpath"
info "Jobs : $jobs"
info "Build Type : $cmake_bt"
info "Extra CXX flags : ${CXX_FLAGS:-<none>}"
info "Python wrapper : $python_wrap"
info "MATLAB wrapper : $matlab_wrap"
info "Generator : $([[ "$use_ninja" == true ]] && echo Ninja || echo 'Unix Makefiles')"
info "Run tests : $run_tests"
info "Install after build: $install"
sleep 0.2
# --- Configure ---
if [[ "$rebuild_only" == false ]]; then
if [[ "$clean_first" == true && -d "$buildpath" ]]; then
info "Removing existing build dir '$buildpath'"
rm -rf -- "$buildpath"
fi
cmake_args=(
-S .
-B "$buildpath"
"-DCMAKE_BUILD_TYPE=$cmake_bt"
"-DCMAKE_CXX_FLAGS=$CXX_FLAGS"
"-DCMAKE_C_FLAGS=$CXX_FLAGS"
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
)
[[ "$use_ninja" == true ]] && cmake_args+=( -G Ninja )
[[ "$python_wrap" == true ]] && cmake_args+=( -DBUILD_PYTHON_WRAPPER=ON )
[[ "$matlab_wrap" == true ]] && cmake_args+=( -DBUILD_MATLAB_WRAPPER=ON )
[[ "$no_optim" == true ]] && cmake_args+=( -DNO_OPTIMIZATION=ON )
info "Configuring with CMake..."
cmake "${cmake_args[@]}"
fi
# --- Build ---
info "Building..."
cmake --build "$buildpath" --parallel "$jobs"
# --- Test ---
if [[ "$run_tests" == true || "$install" == true ]]; then
info "Running tests..."
ctest --test-dir "$buildpath" --output-on-failure -j "$jobs"
fi
# --- Install ---
if [[ "$install" == true ]]; then
info "Installing..."
cmake --build "$buildpath" --parallel "$jobs" --target install
fi
info "Done."