|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +set -euo pipefail |
| 4 | +trap 'echo "❌ Error occurred. Exiting..."; exit 1' ERR |
| 5 | + |
| 6 | +# Constants |
| 7 | +readonly ROOT_DIRECTORY=$(pwd) |
| 8 | +readonly SOURCE_DIRECTORY="$ROOT_DIRECTORY/src" |
| 9 | +readonly COMPILED_CODE_DIRECTORY="$ROOT_DIRECTORY/compiled_code" |
| 10 | +readonly COMPILED_CODE_SOURCE_DIRECTORY="$COMPILED_CODE_DIRECTORY/src" |
| 11 | + |
| 12 | + |
| 13 | +log() { |
| 14 | + echo -e "\033[1;34m[INFO]\033[0m $*" |
| 15 | +} |
| 16 | + |
| 17 | +safe_copy() { |
| 18 | + cp -r "$1" "$2" || { echo "Error: Failed to copy $1"; exit 1; } |
| 19 | +} |
| 20 | + |
| 21 | +find_python_files() { |
| 22 | + find "$SOURCE_DIRECTORY" -name '*.py' -print0 |
| 23 | +} |
| 24 | + |
| 25 | +find_c_files() { |
| 26 | + find "$SOURCE_DIRECTORY" -name '*.c' -print0 |
| 27 | +} |
| 28 | + |
| 29 | +generate_c_files_parallel() { |
| 30 | + log "Generating C files from Python in parallel..." |
| 31 | + find_python_files | xargs -0 -n 1 -P "$(nproc)" -I {} bash -c ' |
| 32 | + f="{}" |
| 33 | + if ! grep -q "# cython: language_level=" "$f"; then |
| 34 | + echo "# cython: language_level=3" | cat - "$f" > tmp && mv tmp "$f" |
| 35 | + fi |
| 36 | + cython "$f" -o "${f%.py}.c" |
| 37 | + ' |
| 38 | +} |
| 39 | + |
| 40 | +compile_c_to_so_parallel() { |
| 41 | + log "Compiling .c files to .so in parallel..." |
| 42 | + find_c_files | xargs -0 -n 1 -P "$(nproc)" -I {} bash -c ' |
| 43 | + c_file="{}" |
| 44 | + source_dir="'"$SOURCE_DIRECTORY"'" |
| 45 | + output_dir="'"$COMPILED_CODE_SOURCE_DIRECTORY"'" |
| 46 | + relative_path="${c_file#$source_dir/}" |
| 47 | + output_subdir="$(dirname "$relative_path")" |
| 48 | + mkdir -p "$output_dir/$output_subdir" |
| 49 | + base_name="$(basename "$c_file" .c)" |
| 50 | + gcc -shared -o "$output_dir/$output_subdir/$base_name.so" -fPIC $(python3 -m pybind11 --includes) "$c_file" |
| 51 | + ' |
| 52 | +} |
| 53 | + |
| 54 | +copy_files() { |
| 55 | + log "Copying project files..." |
| 56 | + safe_copy requirements.txt "$COMPILED_CODE_DIRECTORY" |
| 57 | + safe_copy Dockerfile "$COMPILED_CODE_DIRECTORY" |
| 58 | + safe_copy docker-compose.yml "$COMPILED_CODE_DIRECTORY" |
| 59 | + safe_copy run.sh "$COMPILED_CODE_DIRECTORY" |
| 60 | +} |
| 61 | + |
| 62 | +cleanup() { |
| 63 | + log "Cleaning up generated C files..." |
| 64 | + find "$SOURCE_DIRECTORY" -name "*.c" -delete |
| 65 | + rm -rf build |
| 66 | +} |
| 67 | + |
| 68 | +# Time tracking |
| 69 | +start_timer() { |
| 70 | + date +%s.%N |
| 71 | +} |
| 72 | + |
| 73 | +elapsed_time() { |
| 74 | + start=$1 |
| 75 | + end=$(date +%s.%N) |
| 76 | + echo "$(echo "$end - $start" | bc)" |
| 77 | +} |
| 78 | + |
| 79 | +# ------------------ EXECUTION ------------------ |
| 80 | + |
| 81 | +log "🚀 Build started..." |
| 82 | + |
| 83 | +start=$(start_timer) |
| 84 | +copy_files |
| 85 | +log "✅ Files copied in $(elapsed_time "$start") seconds" |
| 86 | + |
| 87 | +start=$(start_timer) |
| 88 | +generate_c_files_parallel |
| 89 | +log "✅ C files generated in $(elapsed_time "$start") seconds" |
| 90 | + |
| 91 | +start=$(start_timer) |
| 92 | +compile_c_to_so_parallel |
| 93 | +log "✅ Shared objects compiled in $(elapsed_time "$start") seconds" |
| 94 | + |
| 95 | +# Optional cleanup |
| 96 | +# cleanup |
| 97 | + |
| 98 | +log "🎉 Build completed successfully." |
0 commit comments