compile.sh 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #!/bin/bash
  2. # compile.sh - Compile installer sources into a single distributable script
  3. # This script is run during the build process to create the final installer
  4. set -e
  5. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  6. OUTPUT_FILE="${1:-install-usm.sh}"
  7. VERSION="${2:-0.1.0}"
  8. USM_SOURCE_DIR="${3:-$SCRIPT_DIR/../src}"
  9. # Temporary directory for building
  10. WORK_DIR=$(mktemp -d)
  11. trap "rm -rf $WORK_DIR" EXIT
  12. echo "Compiling USM installer..."
  13. echo " Version: $VERSION"
  14. echo " Output: $OUTPUT_FILE"
  15. echo " USM Source: $USM_SOURCE_DIR"
  16. # Step 1: Clone external repositories
  17. echo "Cloning external repositories..."
  18. SOURCES_DIR="$WORK_DIR/sources"
  19. mkdir -p "$SOURCES_DIR"
  20. # Clone Invercargill
  21. if [[ ! -d "$SOURCES_DIR/Invercargill" ]]; then
  22. echo " Cloning Invercargill..."
  23. git clone --depth 1 https://fabrica.unitatem.net/Tilo15/Invercargill.git "$SOURCES_DIR/Invercargill" 2>/dev/null || {
  24. echo "Warning: Could not clone Invercargill, will try without --depth 1"
  25. git clone https://fabrica.unitatem.net/Tilo15/Invercargill.git "$SOURCES_DIR/Invercargill" 2>/dev/null || {
  26. echo "Error: Could not clone Invercargill repository"
  27. exit 1
  28. }
  29. }
  30. fi
  31. # Clone Invercargill-Json
  32. if [[ ! -d "$SOURCES_DIR/Invercargill-Json" ]]; then
  33. echo " Cloning Invercargill-Json..."
  34. git clone --depth 1 https://git.sr.ht/~tilo15/Invercargill-Json "$SOURCES_DIR/Invercargill-Json" 2>/dev/null || {
  35. echo "Warning: Could not clone Invercargill-Json, will try without --depth 1"
  36. git clone https://git.sr.ht/~tilo15/Invercargill-Json "$SOURCES_DIR/Invercargill-Json" 2>/dev/null || {
  37. echo "Error: Could not clone Invercargill-Json repository"
  38. exit 1
  39. }
  40. }
  41. fi
  42. # Copy USM source (USM's meson.build is in src/, not project root)
  43. echo "Copying USM source..."
  44. mkdir -p "$SOURCES_DIR/usm"
  45. # USM_SOURCE_DIR points to the src/ directory which contains meson.build
  46. # Copy the entire src directory contents to usm/
  47. cp -r "$USM_SOURCE_DIR"/* "$SOURCES_DIR/usm/" 2>/dev/null || true
  48. # Copy additional root level files for reference
  49. cp "$USM_SOURCE_DIR/../MANIFEST.usm" "$SOURCES_DIR/usm/" 2>/dev/null || true
  50. cp "$USM_SOURCE_DIR/../usm.config" "$SOURCES_DIR/usm/" 2>/dev/null || true
  51. # The DNF SPM helper lives in spm/ at the project root, outside src/, but
  52. # src/meson.build configures it via '../spm/dnf/usm-spm-dnf' — the payload
  53. # must therefore carry spm/ as a SIBLING of usm/ so the relative input
  54. # resolves inside the extracted tree
  55. echo "Copying USM SPM helper..."
  56. mkdir -p "$SOURCES_DIR/spm"
  57. cp -r "$USM_SOURCE_DIR/../spm"/* "$SOURCES_DIR/spm/" 2>/dev/null || {
  58. echo "Error: Could not copy the spm/ directory from next to $USM_SOURCE_DIR"
  59. exit 1
  60. }
  61. # Step 2: Create the combined script header
  62. echo "Building combined script..."
  63. HEADER_FILE="$WORK_DIR/header.sh"
  64. cat > "$HEADER_FILE" << SCRIPT_HEADER
  65. #!/bin/bash
  66. # USM Installer - self-contained installation script
  67. # This script was automatically generated. Do not edit.
  68. # Version: $VERSION
  69. # Generated: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
  70. set -e
  71. SCRIPT_HEADER
  72. # Step 3: Auto-detect package manager implementations
  73. PM_IMPLEMENTATIONS=()
  74. for pm_file in "$SCRIPT_DIR"/pm_*.sh; do
  75. if [[ -f "$pm_file" ]]; then
  76. # Extract PM name from filename (pm_apt.sh -> apt)
  77. pm_name=$(basename "$pm_file" .sh | sed 's/^pm_//')
  78. # Skip pm_base.sh - it's the interface, not an implementation
  79. if [[ "$pm_name" != "base" ]]; then
  80. PM_IMPLEMENTATIONS+=("$pm_name")
  81. fi
  82. fi
  83. done
  84. echo " Detected package managers: ${PM_IMPLEMENTATIONS[*]}"
  85. # Step 4: Combine all shell scripts
  86. COMBINED_FILE="$WORK_DIR/combined.sh"
  87. # Build the PM implementations array initialization
  88. PM_ARRAY_FILE="$WORK_DIR/pm_array.sh"
  89. cat > "$PM_ARRAY_FILE" << PM_ARRAY
  90. # Auto-detected package manager implementations
  91. PM_IMPLEMENTATIONS=(${PM_IMPLEMENTATIONS[*]})
  92. PM_ARRAY
  93. # Function to process a script file
  94. process_script() {
  95. local file="$1"
  96. local section="$2"
  97. echo "# === $section ==="
  98. cat "$file"
  99. }
  100. # Combine scripts in order
  101. {
  102. process_script "$SCRIPT_DIR/utils.sh" "Utils"
  103. echo ""
  104. process_script "$SCRIPT_DIR/ui.sh" "UI"
  105. echo ""
  106. # Include PM implementations first
  107. for pm_name in "${PM_IMPLEMENTATIONS[@]}"; do
  108. process_script "$SCRIPT_DIR/pm_${pm_name}.sh" "Package Manager ${pm_name}"
  109. echo ""
  110. done
  111. # Include PM array initialization
  112. cat "$PM_ARRAY_FILE"
  113. echo ""
  114. # Include pm_base which uses the array
  115. process_script "$SCRIPT_DIR/pm_base.sh" "Package Manager Base"
  116. echo ""
  117. process_script "$SCRIPT_DIR/build_config.sh" "Build Config"
  118. echo ""
  119. process_script "$SCRIPT_DIR/main.sh" "Main"
  120. echo ""
  121. # Add the main call at the very end
  122. echo "# Run main function"
  123. echo 'main "$@"'
  124. echo ""
  125. echo "# Exit before payload"
  126. echo "exit 0"
  127. } > "$COMBINED_FILE"
  128. # Replace version placeholder in combined file
  129. sed -i "s/@VERSION@/$VERSION/g" "$COMBINED_FILE"
  130. # Step 5: Create the payload
  131. echo "Creating compressed payload..."
  132. PAYLOAD_FILE="$WORK_DIR/payload.tar.xz"
  133. # Use highest compression for smaller file size
  134. tar -C "$SOURCES_DIR" -cf - . | xz -9 -T0 > "$PAYLOAD_FILE"
  135. # Step 6: Assemble final installer
  136. echo "Assembling final installer..."
  137. {
  138. cat "$HEADER_FILE"
  139. cat "$COMBINED_FILE"
  140. echo ""
  141. echo "__PAYLOAD_START__"
  142. cat "$PAYLOAD_FILE"
  143. } > "$OUTPUT_FILE"
  144. # Make executable
  145. chmod +x "$OUTPUT_FILE"
  146. # Calculate output size
  147. OUTPUT_SIZE=$(du -h "$OUTPUT_FILE" | cut -f1)
  148. echo ""
  149. echo "✓ Installer created successfully!"
  150. echo " Output: $OUTPUT_FILE"
  151. echo " Size: $OUTPUT_SIZE"