#!/usr/bin/env bash # Programs declare -A PROGRAMS PROGRAMS[HelloWorld]="HelloWorld" PROGRAMS[FizzBuzz]="FizzBuzz" PROGRAMS[RecurringRainfall]="RecurringRainfall" PROGRAMS[ProducerConsumer]="ProducerConsumer" PROGRAMS[ArrayStack]="ArrayStack" PROGRAMS[Endian]="Endian" PROGRAMS[BreakMemory]="BreakMemory" PROGRAMS[AddTwoNumbers]="l33tcode_addtwonumbers" PROGRAMS[MedianOfSortedArrays]="l33tcode_medianofsortedarrays" PROGRAMS[ReverseWords]="l33tcode_reversewords" PROGRAMS[merge2sortedlists]="l33tcode_merge2sortedlists" ######################### # DON'T EDIT BELOW HERE # ######################### declare -A CC_EXISTS declare -A CC_EXE declare -A CC_OPTS declare -A LINK_OPTS operating_system=$(uname) # Detect command line if [ $# == 0 ] || [ $1 == 'opt' ]; then echo "[INFO] Enabling optimizations and Enabling debugging" ENABLE_OPTS=true ENABLE_DEBUG=true elif [ $1 == 'help' ]; then echo "Usage: gen_makefiles.sh " echo " args:" echo " help - This message" echo " debug - Generate makefiles with optimizations off and debugging enabled" echo " opt - Generate makefiles with optimizations on and debugging enabled" echo " release - Generate makefiles with optimizations and debugging disabled" echo " If no args are provided, opt is the default" exit 1 elif [ $1 == 'debug' ]; then echo "[INFO] Disabling optimizations and Enabling debugging" ENABLE_OPTS=false ENABLE_DEBUG=true elif [ $1 == 'release' ]; then echo "[INFO] Enabling optimizations and Disabling debugging" ENABLE_OPTS=true ENABLE_DEBUG=false else echo "[ERR] Unknown option, use gen_makefiles.sh help for help" exit 2 fi ################### # Detect compilers # # Tries to find the compilers on the host system # If a compiler isn't found, it won't generate makefiles for that target # # Priority order: # LLVM -> GCC -> Closed Source function detect_compilers() { # Handy default to avoid copy/paste INTERNAL_GCC_WARNINGS="-Wall" if [ $ENABLE_OPTS == 'true' ]; then INTERNAL_GCC_STYLE_DEFAULT_OPTS="-O3" fi if [ $ENABLE_DEBUG == 'true' ]; then INTERNAL_GCC_STYLE_DEBUG="-g" fi INTERNAL_GCC_STYLE_FLAGS="$INTERNAL_GCC_STYLE_DEFAULT_OPTS $INTERNAL_GCC_WARNINGS $INTERNAL_GCC_STYLE_DEBUG" # Ada Compiler type -a gnatmake &> /dev/null if [ $? == 0 ]; then echo [INFO] Found Ada gnatmake, using gnatmake for Ada CC_EXISTS['Ada']=true CC_EXE['Ada']=gnatmake CC_OPTS['Ada']=$INTERNAL_GCC_STYLE_FLAGS else echo [WARN] No Ada compiler found, no Ada makefiles will be generated fi # C Compiler type -a clang &> /dev/null INT_HAS_CLANG=$? type -a gcc &> /dev/null INT_HAS_GCC=$? if [ $INT_HAS_CLANG == 0 ]; then echo [INFO] Found clang, using clang for C CC_EXISTS['C']=true CC_EXE['C']=clang CC_OPTS['C']=$INTERNAL_GCC_STYLE_FLAGS elif [ $INT_HAS_GCC == 0 ]; then echo [INFO] No clang, found gcc, using gcc for C CC_EXISTS['C']=true CC_EXE['C']=gcc CC_OPTS['C']=$INTERNAL_GCC_STYLE_FLAGS else echo [WARN] No C compiler found, no C makefiles will be generated fi # Cpp Compiler type -a clang++ &> /dev/null INT_HAS_CLANGPP=$? type -a g++ &> /dev/null INT_HAS_GPP=$? if [ $INT_HAS_CLANGPP == 0 ]; then echo [INFO] Found clang++, using clang for C++ CC_EXISTS['Cpp']=true CC_EXE['Cpp']=clang++ CC_OPTS['Cpp']=$INTERNAL_GCC_STYLE_FLAGS elif [ $INT_HAS_GPP == 0 ]; then echo [INFO] No clang++, found g++, using g++ for C++ CC_EXISTS['Cpp']=true CC_EXE['Cpp']=g++ CC_OPTS['Cpp']=$INTERNAL_GCC_STYLE_FLAGS else echo [WARN] No C++ compiler found, no C++ makefiles will be generated fi if [ $operating_system == 'Linux' ]; then LINK_OPTS['Cpp']="-lpthread" elif [ $operating_system == 'FreeBSD' ]; then LINK_OPTS['Cpp']="-lpthread" fi # C# Compiler type -a mcs &> /dev/null if [ $? == 0 ]; then echo [INFO] Found mcs, using mcs for C# CC_EXISTS['CSharp']=true CC_EXE['CSharp']=mcs if [ $ENABLE_DEBUG == true ]; then CSHARP_DEBUG="-debug" fi if [ $ENABLE_OPTS == true ]; then CSHARP_OPTS="-optimize" fi CC_OPTS['CSharp']="$CSHARP_DEBUG $CSHARP_OPTS" else echo [WARN] No C# compiler found, no C# makefiles will be generated fi # D Compiler type -a ldc2 &> /dev/null INT_HAS_LDC2=$? type -a gdc &> /dev/null INT_HAS_GDC=$? if [ $INT_HAS_LDC2 == 0 ]; then echo [INFO] Found ldc2, using ldc2 for D CC_EXISTS['D']=true CC_EXE['D']=ldc2 if [ $ENABLE_DEBUG == true ]; then D_DEBUG="-g" fi if [ $ENABLE_OPTS == true ]; then D_OPTS="-O3" fi CC_OPTS['D']="$D_DEBUG $D_OPTS" elif [ $INT_HAS_GDC == 0 ]; then echo [INFO] No ldc2, found gdc, using gdc for D CC_EXISTS['D']=true CC_EXE['D']=gdc CC_OPTS['D']=$INTERNAL_GCC_STYLE_FLAGS else echo [WARN] No D compiler found, no D makefiles will be generated fi # Fortran compiler type -a flang &> /dev/null INT_HAS_FLANG=$? type -a gfortran &> /dev/null INT_HAS_GFORTRAN=$? if [ $INT_HAS_FLANG == 0 ]; then echo [INFO] Found flang, using flang for Fortran CC_EXISTS['Fortran']=true CC_EXE['Fortran']=flang if [ $operating_system == 'FreeBSD' ]; then CC_OPTS['Fortran']="$INTERNAL_GCC_STYLE_FLAGS -lexecinfo" else CC_OPTS['Fortran']=$INTERNAL_GCC_STYLE_FLAGS fi elif [ $INT_HAS_GFORTRAN == 0 ]; then echo [INFO] No flang, found gfortran, using gfortran for Fortran CC_EXISTS['Fortran']=true CC_EXE['Fortran']=gfortran CC_OPTS['Fortran']=$INTERNAL_GCC_STYLE_FLAGS else echo [WARN] No Fortran compiler found, no Fortran makefiles will be generated fi # Haskell Compiler type -a ghc &> /dev/null if [ $? == 0 ]; then echo [INFO] Found ghc, using ghc for Haskell CC_EXISTS['Haskell']=true CC_EXE['Haskell']=ghc if [ $ENABLE_DEBUG == true ]; then HASKELL_DEBUG="-g" fi if [ $ENABLE_OPTS == true ]; then HASKELL_OPTS="-O3" fi CC_OPTS['Haskell']="-Wall $HASKELL_DEBUG $HASKELL_OPTS" else echo [WARN] No Haskell compiler found, no Haskell makefiles will be generated fi # Java compiler type -a javac &> /dev/null if [ $? == 0 ]; then echo [INFO] Found javac, using javac for Java CC_EXISTS['Java']=true CC_EXE['Java']=javac CC_OPTS['Java']= if [ $ENABLE_DEBUG == true ]; then CC_OPTS['Java']="-g" fi else echo [WARN] No Java compiler found, no Java makefiles will be generated fi # Rust compiler type -a rustc &> /dev/null if [ $? == 0 ]; then echo [INFO] Found rustc, using rustc for Rust CC_EXISTS['Rust']=true CC_EXE['Rust']=rustc if [ $ENABLE_DEBUG == true ]; then RUST_DEBUG="-g" fi if [ $ENABLE_OPTS == true ]; then RUST_OPTS="-C opt-level=3" fi CC_OPTS['Rust']="$RUST_DEBUG $RUST_OPTS" else echo [WARN] No Rust compiler found, no Rust makefiles will be generated fi } function gen_std_program_makefile() { declare makefile=$1 echo "\$(PROB): \$(DIR)/\$(PROB).\$(EXT)" >> $makefile printf "\t%s\n\n" "\$(CC) \$(CC_OPTS) -o \$(PROB) \$(DIR)/\$(PROB).\$(EXT) \$(LINK_OPTS)" >> $makefile echo "clean:" >> $makefile printf "\t%s\n" "rm \$(PROB)" >> $makefile } function gen_ghc_program_makefile() { declare makefile=$1 echo "\$(PROB): \$(DIR)/\$(PROB).\$(EXT)" >> $makefile printf "\t%s\n\n" "\$(CC) \$(CC_OPTS) -o \$(PROB) \$(DIR)/\$(PROB).\$(EXT)" >> $makefile echo "clean:" >> $makefile printf "\t%s\n" "rm \$(PROB) \$(DIR)/\$(PROB).o \$(DIR)/\$(PROB).hi" >> $makefile } function gen_gnat_program_makefile() { declare makefile=$1 echo "\$(PROB): \$(DIR)/\$(PROB).\$(EXT)" >> $makefile printf "\t%s\n\n" "\$(CC) \$(CC_OPTS) -o \$(PROB) \$(DIR)/\$(PROB).\$(EXT)" >> $makefile echo "clean:" >> $makefile printf "\t%s\n" "rm \$(PROB) \$(PROB).o \$(PROB).ali" >> $makefile } function gen_ldc_program_makefile() { declare makefile=$1 echo "\$(PROB): \$(DIR)/\$(PROB).\$(EXT)" >> $makefile printf "\t%s\n\n" "\$(CC) \$(CC_OPTS) -of=\$(PROB) \$(DIR)/\$(PROB).\$(EXT)" >> $makefile echo "clean:" >> $makefile printf "\t%s\n" "rm \$(PROB) \$(PROB).o" >> $makefile } function gen_mcs_program_makefile() { declare makefile=$1 echo "\$(PROB): \$(DIR)/\$(PROB).\$(EXT)" >> $makefile printf "\t%s\n\n" "\$(CC) \$(CC_OPTS) -out:\$(PROB) \$(DIR)/\$(PROB).\$(EXT)" >> $makefile echo "clean:" >> $makefile printf "\t%s\n" "rm \$(PROB)" >> $makefile } function gen_javac_program_makefile() { declare makefile=$1 echo "\$(PROB).class: \$(DIR)/\$(PROB).\$(EXT)" >> $makefile printf "\t%s\n\n" "\$(CC) \$(CC_OPTS) -d . \$(DIR)/\$(PROB).\$(EXT)" >> $makefile echo "clean:" >> $makefile printf "\t%s\n" "rm *.class" >> $makefile } function gen_Ada_program_makefile() { declare program=$1 declare makefile=$2 declare src_dir=$3 declare cc_exe=$4 declare cc_opts=$5 echo [GEN] Writing makefile for Ada:$program to $makefile echo PROB=${program,,} > $makefile echo EXT=adb >> $makefile echo CC=$cc_exe >> $makefile echo CC_OPTS=$cc_opts >> $makefile echo DIR=$src_dir >> $makefile echo "" >> $makefile gen_gnat_program_makefile $makefile } function gen_C_program_makefile() { declare program=$1 declare makefile=$2 declare src_dir=$3 declare cc_exe=$4 declare cc_opts=$5 declare link_opts=$6 echo [GEN] Writing makefile for C:$program to $makefile echo PROB=${program,,} > $makefile echo EXT=c >> $makefile echo CC=$cc_exe >> $makefile echo CC_OPTS=$cc_opts >> $makefile echo LINK_OPTS=$link_opts >> $makefile echo DIR=$src_dir >> $makefile echo "" >> $makefile gen_std_program_makefile $makefile } function gen_Cpp_program_makefile() { declare program=$1 declare makefile=$2 declare src_dir=$3 declare cc_exe=$4 declare cc_opts=$5 declare link_opts=$6 echo [GEN] Writing makefile for Cpp:$program to $makefile echo PROB=${program,,} > $makefile echo EXT=cpp >> $makefile echo CC=$cc_exe >> $makefile echo CC_OPTS=$cc_opts >> $makefile echo LINK_OPTS=$link_opts >> $makefile echo DIR=$src_dir >> $makefile echo "" >> $makefile gen_std_program_makefile $makefile } function gen_CSharp_program_makefile() { declare program=$1 declare makefile=$2 declare src_dir=$3 declare cc_exe=$4 declare cc_opts=$5 echo [GEN] Writing makefile for CSharp:$program to $makefile echo PROB=${program,,} > $makefile echo EXT=cs >> $makefile echo CC=$cc_exe >> $makefile echo CC_OPTS=$cc_opts >> $makefile echo DIR=$src_dir >> $makefile echo "" >> $makefile gen_mcs_program_makefile $makefile } function gen_D_program_makefile() { declare program=$1 declare makefile=$2 declare src_dir=$3 declare cc_exe=$4 declare cc_opts=$5 echo [GEN] Writing makefile for D:$program to $makefile echo PROB=${program,,} > $makefile echo EXT=d >> $makefile echo CC=$cc_exe >> $makefile echo CC_OPTS=$cc_opts >> $makefile echo DIR=$src_dir >> $makefile echo "" >> $makefile if [[ $cc_exe == ldc2 ]]; then gen_ldc_program_makefile $makefile else gen_std_program_makefile $makefile fi } function gen_Fortran_program_makefile() { declare program=$1 declare makefile=$2 declare src_dir=$3 declare cc_exe=$4 declare cc_opts=$5 echo [GEN] Writing makefile for Fortran:$program to $makefile echo PROB=${program,,} > $makefile echo EXT=f90 >> $makefile echo CC=$cc_exe >> $makefile echo CC_OPTS=$cc_opts >> $makefile echo DIR=$src_dir >> $makefile echo "" >> $makefile gen_std_program_makefile $makefile } function gen_Haskell_program_makefile() { declare program=$1 declare makefile=$2 declare src_dir=$3 declare cc_exe=$4 declare cc_opts=$5 echo [GEN] Writing makefile for Haskell:$program to $makefile echo PROB=${program,,} > $makefile echo EXT=hs >> $makefile echo CC=$cc_exe >> $makefile echo CC_OPTS=$cc_opts >> $makefile echo DIR=$src_dir >> $makefile echo "" >> $makefile gen_ghc_program_makefile $makefile } function gen_Java_program_makefile() { declare program=$1 declare makefile=$2 declare src_dir=$3 declare cc_exe=$4 declare cc_opts=$5 echo [GEN] Writing makefile for Java:$program to $makefile echo PROB=${program,,} > $makefile echo EXT=java >> $makefile echo CC=$cc_exe >> $makefile echo CC_OPTS=$cc_opts >> $makefile echo DIR=$src_dir >> $makefile echo "" >> $makefile gen_javac_program_makefile $makefile } function gen_Rust_program_makefile() { declare program=$1 declare makefile=$2 declare src_dir=$3 declare cc_exe=$4 declare cc_opts=$5 echo [GEN] Writing makefile for Rust:$program to $makefile echo PROB=${program,,} > $makefile echo EXT=rs >> $makefile echo CC=$cc_exe >> $makefile echo CC_OPTS=$cc_opts >> $makefile echo DIR=$src_dir >> $makefile echo "" >> $makefile gen_std_program_makefile $makefile } function gen_program_makefile() { declare program=$1 echo [INFO] Writing makes files for $program cd $program for lang_name in *; do if [ ${CC_EXISTS[${lang_name}]} ]; then mkdir -p ../build/$program/$lang_name COMMAND="gen_${lang_name}_program_makefile $program ../build/$program/$lang_name/Makefile ../../../$program/$lang_name ${CC_EXE[${lang_name}]} '${CC_OPTS[${lang_name}]}' '${LINK_OPTS[${lang_name}]}'" eval $COMMAND else echo [INFO] $lang_name has no compiler, skipping makefile generation fi done cd .. } detect_compilers for program in "${PROGRAMS[@]}"; do gen_program_makefile $program done