#!/bin/bash # build-macos.sh - macOS-specific build logic using clang # Handles Objective-C++ files, frameworks, etc. # Usage: ./build-macos.sh [debug|release] [x64|x86|arm64] set -e # Exit on error # ============================================================================= # Configuration # ============================================================================= SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" CONFIG_DIR="$SCRIPT_DIR/../config" # Source configuration files source "$CONFIG_DIR/build-config.sh" source "$HELPERS_DIR/print-routines.sh" source "$HELPERS_DIR/copy-resources.sh" # ============================================================================= # Platform-specific settings # ============================================================================= setup_macos_vars() { local config=$1 local arch=$2 # Use directories from build-config.sh (already set to absolute paths) # BUILD_DIR, CODE_DIR, CUSTOM_DIR, FOREIGN_DIR are already set # Compiler CXX="clang++" CC="clang" # Base flags for macOS COMMON_FLAGS=( "${CLANG_OPTS_MACOS[@]}" "-I$CODE_DIR" "-I$FOREIGN_DIR/freetype2" ) # Architecture-specific flags case "$arch" in "x64") ARCH_FLAGS=("${ARCH_FLAGS_X64[@]}") FREETYPE_LIB="$FREETYPE_LIB_MACOS_X64" ;; "arm64") ARCH_FLAGS=("-arch" "arm64" "-DFTECH_64_BIT") FREETYPE_LIB="$FREETYPE_LIB_MACOS_X64" # Use x64 lib for now ;; "x86") ARCH_FLAGS=("${ARCH_FLAGS_X86[@]}") FREETYPE_LIB="$FREETYPE_LIB_MACOS_X86" ;; *) echo "Error: Unsupported architecture: $arch" >&2 return 1 ;; esac # Configuration-specific flags case "$config" in "debug") CONFIG_FLAGS=("${DEBUG_FLAGS[@]}") ;; "release") CONFIG_FLAGS=("${RELEASE_FLAGS[@]}") ;; *) echo "Error: Unsupported config: $config" >&2 return 1 ;; esac # Combine all flags COMPILE_FLAGS=( "${COMMON_FLAGS[@]}" "${ARCH_FLAGS[@]}" "${CONFIG_FLAGS[@]}" ) # Libraries and frameworks LINK_LIBS=( "${FRAMEWORKS_MACOS[@]}" "$FREETYPE_LIB" ) # Platform includes PLATFORM_INCLUDES=() for inc in "${PLATFORM_INCLUDES_MACOS[@]}"; do PLATFORM_INCLUDES+=("-I$CODE_DIR/$inc") done print_info "macOS build configuration:" print_info " Architecture: $arch" print_info " Configuration: $config" print_info " Compiler: $CXX" print_info " FreeType: $FREETYPE_LIB" } # ============================================================================= # Build functions # ============================================================================= build_core_engine() { print_step "Building API Parser..." $CUSTOM_DIR/bin/build_one_time.sh $CODE_DIR/4ed_api_parser_main.cpp $BUILD_DIR && cp $BUILD_DIR/one_time $BUILD_DIR/api_parser print_step "Building System API..." $CUSTOM_DIR/bin/build_one_time.sh $CODE_DIR/4ed_system_api.cpp $BUILD_DIR && $BUILD_DIR/one_time print_step "Building API Check..." $CUSTOM_DIR/bin/build_one_time.sh $CODE_DIR/4ed_api_check.cpp $BUILD_DIR && cp $BUILD_DIR/one_time $BUILD_DIR/api_checker print_step "Running API Parser..." $BUILD_DIR/api_parser $CODE_DIR/4ed_api_implementation.cpp print_step "Building Font API..." $CUSTOM_DIR/bin/build_one_time.sh $CODE_DIR/4ed_font_api.cpp $BUILD_DIR && $BUILD_DIR/one_time print_step "Building Graphics API..." $CUSTOM_DIR/bin/build_one_time.sh $CODE_DIR/4ed_graphics_api.cpp $BUILD_DIR && $BUILD_DIR/one_time print_step "Building core engine (4ed_app.so)" local app_target="$CODE_DIR/4ed_app_target.cpp" local output_lib="$BUILD_DIR/4ed_app.so" # Build flags for shared library local build_flags=( "${COMPILE_FLAGS[@]}" "-shared" "-fPIC" "-DFRED_SUPER" "-DFRED_INTERNAL" ) # Include directories for custom layer local include_flags=( "-I$CUSTOM_DIR" "-I$CUSTOM_DIR/generated" ) print_info "Compiling core application library..." print_info "Input: $app_target" print_info "Output: $output_lib" # Compile core application shared library if [[ "${BUILD_VERBOSE:-}" == "1" ]]; then echo "Executing: $CXX ${build_flags[*]} ${include_flags[*]} -o $output_lib $app_target ${LINK_LIBS[*]}" fi $CXX \ "${build_flags[@]}" \ "${include_flags[@]}" \ -o "$output_lib" \ "$app_target" \ "${LINK_LIBS[@]}" print_success "Core engine built successfully" } build_platform_layer() { print_step "Building platform layer (4ed executable)" local platform_source="$CODE_DIR/platform_mac/mac_4ed.mm" local output_exe="$BUILD_DIR/4ed" local include_flags=( "-I$CUSTOM_DIR" ) # Build flags for executable local build_flags=( "${COMPILE_FLAGS[@]}" "${PLATFORM_INCLUDES[@]}" "${include_flags[@]}" "-DFRED_SUPER" "-DFRED_INTERNAL" ) print_info "Compiling platform layer executable..." print_info "Input: $platform_source" print_info "Output: $output_exe" # Compile platform layer executable if [[ "${BUILD_VERBOSE:-}" == "1" ]]; then echo "Executing: $CXX ${build_flags[*]} -o $output_exe $platform_source ${LINK_LIBS[*]}" fi $CXX \ "${build_flags[@]}" \ -o "$output_exe" \ "$platform_source" \ "${LINK_LIBS[@]}" print_success "Platform layer built successfully" } build_custom_layer() { print_step "Building custom layer (custom_4coder.so)" local custom_target="$CUSTOM_DIR/4coder_default_bindings.cpp" local output_lib="$BUILD_DIR/custom_4coder.so" local temp_dir="$BUILD_DIR/temp" # Create temp directory mkdir -p "$temp_dir" # Multi-stage custom layer build process # Stage 0: Build and Run Generators mkdir -p "$CODE_DIR/generated" print_step "Building CPP Lexer Gen..." $CUSTOM_DIR/bin/build_one_time.sh $CUSTOM_DIR/languages/4coder_cpp_lexer_gen.cpp $BUILD_DIR && $BUILD_DIR/one_time print_step "Building Generate Keycodes..." $CUSTOM_DIR/bin/build_one_time.sh $CODE_DIR/4ed_generate_keycodes.cpp $BUILD_DIR && $BUILD_DIR/one_time print_step "Building Docs..." $CUSTOM_DIR/bin/build_one_time.sh $CODE_DIR/docs/4ed_doc_custom_api_main.cpp $BUILD_DIR && $BUILD_DIR/one_time # Ensure generated directory exists mkdir -p "$CUSTOM_DIR/generated" # Stage 3: Generate metadata $SCRIPTS_DIR/build-metadata.sh print_success "Metadata generated" # Stage 4: Compile custom layer shared library print_info "Stage 4: Compiling custom layer shared library..." local build_flags=( "${COMPILE_FLAGS[@]}" "-shared" "-fPIC" "-I$CUSTOM_DIR" "-I$CUSTOM_DIR/generated" "-DFRED_SUPER" "-DFRED_INTERNAL" ) if [[ "${BUILD_VERBOSE:-}" == "1" ]]; then echo "Executing: $CXX ${build_flags[*]} -o $output_lib $custom_target" fi $CXX \ "${build_flags[@]}" \ -o "$output_lib" \ "$custom_target" print_success "Custom layer built successfully" # Clean up temporary files print_info "Cleaning up temporary files..." # rm -f "$preprocessed_file" "$metadata_generator" } validate_build() { print_step "Validating build outputs" local all_good=true local expected_files=("4ed" "4ed_app.so" "custom_4coder.so") for file in "${expected_files[@]}"; do if [[ -f "$BUILD_DIR/$file" ]]; then local file_size file_size=$(stat -f%z "$BUILD_DIR/$file" 2>/dev/null || echo "unknown") print_success "$file (${file_size} bytes)" else echo -e "${RED}✗${NC} Missing: $file" all_good=false fi done if [[ "$all_good" == "true" ]]; then print_success "All build outputs validated" return 0 else echo -e "${RED}✗${NC} Build validation failed" return 1 fi } # ============================================================================= # Main execution # ============================================================================= main() { local config="${1:-debug}" local arch="${2:-x64}" print_step "macOS Build Process" print_info "Configuration: $config" print_info "Architecture: $arch" # Setup platform-specific variables setup_macos_vars "$config" "$arch" # Create build directory mkdir -p "$BUILD_DIR" # Execute build steps build_custom_layer build_core_engine build_platform_layer copy_resources validate_build print_success "macOS build completed successfully!" } # Only run main if script is executed directly (not sourced) if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" fi