#!/bin/bash

# Copyright (c) 1999,2000,2002-2007,2009,2011,2012
# Utrecht University (The Netherlands),
# ETH Zurich (Switzerland),
# INRIA Sophia-Antipolis (France),
# Max-Planck-Institute for Informatics Saarbruecken (Germany),
# and Tel-Aviv University (Israel).  All rights reserved.
#
# This file is part of CGAL (www.cgal.org)
#
# $URL$
# $Id$
# SPDX-License-Identifier: LGPL-3.0-or-later
#
# Author(s)     : various

# This script creates a CGAL cmake script with entries for files with a common
# C++ file extension (as mentioned in the g++ man page) in the current directory.
# Some options can be given or specified in a file.


#LEDA
#GMP
#GMPXX
#MPFR
#MPFI
#RS
#BLAS
#LAPACK
#ESBTL
#NTL

#Core (implies GMP+GMPXX)
#ImageIO

#not (yet) supported
#F2C (comes with BLAS/LAPACK - something like that)
#IPE (ask Laurent)
#MKL (ask Andreas)

create_cmake_script_with_options()
{
  # parse options file
  if [ -e "$OPTIONS_FILE" ]; then

    OLDIFS="$IFS"
    IFS=$'\n'
    for LINE in `cat $OPTIONS_FILE`; do

      # CGAL components
      if [ -z "$CGAL_COMPONENTS_GIVEN" ]; then # read file only if not given!
        next_cgal_component=`echo $LINE | grep -v "#" | grep CGAL_COMPONENT`
        if [ ! -z "$next_cgal_component" ]; then
          next_cgal_component=${next_cgal_component/CGAL_COMPONENT /}
          if [ -z "$CGAL_COMPONENTS" ]; then
            CGAL_COMPONENTS=$next_cgal_component
          else
            CGAL_COMPONENTS=$CGAL_COMPONENTS":"$next_cgal_component
          fi
        fi
      fi

      # Boost components
      if [ -z "$BOOST_COMPONENTS_GIVEN" ]; then # read file only if not given!
        next_boost_component=`echo $LINE | grep -v "#" | grep BOOST_COMPONENT`
        if [ ! -z "$next_boost_component" ]; then
          next_boost_component=${next_boost_component/BOOST_COMPONENT /}
          if [ -z "$BOOST_COMPONENTS" ]; then
            BOOST_COMPONENTS=$next_boost_component
          else
            BOOST_COMPONENTS=$BOOST_COMPONENTS":"$next_boost_component
          fi
        fi
      fi

    done
    IFS="$OLDIFS"
  fi


  # print makefile header
  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'
# Created by the script cgal_create_CMakeLists
# This is the CMake script for compiling a set of CGAL applications.

cmake_minimum_required(VERSION 3.12...3.31)

EOF
  #---------------------------------------------------------------------------
  if [ "$SINGLE_SOURCE" = "n" ]; then
    echo "project( ${PROJECT} )"
  else
    echo "project( ${SOURCE} )"
  fi

  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'


# CGAL and its components
EOF
if [ -n "$ENABLE_CTEST" ]; then
  echo "enable_testing()"
fi
  #---------------------------------------------------------------------------
  # echo "CGAL_COMPONENTS: $CGAL_COMPONENTS"
  if [ ! -z "$CGAL_COMPONENTS" ]; then
    # ensure capitalization

    # CGAL: Core,  PDB, ImageIO
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[c|C][o|O][r|R][e|E]/Core}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[i|I][m|M][a|A][g|G][e|E][i|I][o|O]/ImageIO}

    # external libs

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[g|G][m|M][p|P]/GMP}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[g|G][m|M][p|P][x|X][x|X]/GMPXX}

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[m|M][p|P][f|F][r|R]/MPFR}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[l|L][e|E][d|D][a|A]/LEDA}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[m|M][p|P][f|F][i|I]/MPFI}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[r|R][s|S]/RS}

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[b|B][l|L][a|A][s|S]/BLAS}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[l|L][a|A][p|P][a|A][c|C][k|K]/LAPACK}

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[q|Q][g|G][l|L][v|V][i|I][e|E][w|W][e|E][r|R]/QGLViewer}

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[z|Z][l|L][i|I][b|B]/zlib}

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[e|E][s|S][b|B][t|T][l|L]/ESBTL}

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[n|N][t|T][l|L]/NTL}

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[o|O][p|P][e|E][n|N][g|G][l|L]/OpenGL}


#F2C?
#IPE?
#MKL?

    OLDIFS="$IFS"
    IFS=':'
    for cgal_component in $CGAL_COMPONENTS; do
      COMPONENT=`echo $cgal_component | tr '[:upper:]' '[:lower:]'`

    done
    IFS=$OLDIFS

  fi

  echo "find_package( CGAL QUIET COMPONENTS ${CGAL_COMPONENTS//:/ } )"

  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'

if ( NOT CGAL_FOUND )

  message(STATUS "This project requires the CGAL library, and will not be compiled.")
  return()

endif()

EOF
  #---------------------------------------------------------------------------

  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'

# Boost and its components
EOF
  #---------------------------------------------------------------------------

  if [ ! -z "$BOOST_COMPONENTS" ]; then

    echo "find_package( Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS//:/ } )"

  else

    echo "find_package( Boost REQUIRED )"

  fi # additional Boost components

  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'

if ( NOT Boost_FOUND )

  message(STATUS "This project requires the Boost library, and will not be compiled.")

  return()

endif()
EOF
  #---------------------------------------------------------------------------


  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'

# include for local directory
EOF
  #---------------------------------------------------------------------------

  if [ -d include ] ; then
    echo 'include_directories( BEFORE include )'
  fi

  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'

# include for local package
EOF
  #---------------------------------------------------------------------------

  # includes for local package
  if [ -d ../include ] ; then
    echo 'include_directories( BEFORE ../include )'
  fi

  if [ ! -z "$PACKAGES" ]; then
    #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    cat << 'EOF'

# include of additional packages
EOF
    #-------------------------------------------------------------------------
  fi

  if [ ! -z "$BOOST_COMPONENTS" ]; then
    #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    cat << 'EOF'

# Boost linking
EOF
    #-------------------------------------------------------------------------

    OLDIFS="$IFS"
    IFS=':'
    for boost_component in $BOOST_COMPONENTS; do
      BOOST_COMPONENT=`echo $boost_component | tr '[:lower:]' '[:upper:]'`
      echo "add_definitions( \"-DCGAL_USE_BOOST_${BOOST_COMPONENT}\" )"
      echo "list(APPEND CGAL_3RD_PARTY_LIBRARIES \${Boost_${BOOST_COMPONENT}_LIBRARY} )"
    done
    IFS=$OLDIFS

  fi # additional Boost components


  # All Files or Single Source

  if [ "$SINGLE_SOURCE" = "n" ]; then #=======================================

    ###############
    # ALL SOURCES #
    ###############

    #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    cat << 'EOF'


# Creating entries for all C++ files with "main" routine
# ##########################################################

EOF
    #-------------------------------------------------------------------------


    # add a new line
    echo

    for file in `ls *.cc *.cp *.cxx *.cpp *.CPP *.c++ *.C 2> /dev/null | sort` ; do
      # Create an executable for each cpp that  contains a function "main()"
      BASE=`basename $file .cc`
      BASE=`basename $BASE .cp`
      BASE=`basename $BASE .cxx`
      BASE=`basename $BASE .cpp`
      BASE=`basename $BASE .CPP`
      BASE=`basename $BASE .c++`
      BASE=`basename $BASE .C`
      grep -E '\bmain[ \t]*\(' $file >/dev/null 2>&1
      if [ $? -eq 0 ]; then
        echo "create_single_source_cgal_program( \"$file\" )"
        if [ -n "$ENABLE_CTEST" ]; then
          if [ -f "$BASE.cin" ] ; then
            CIN=" < $BASE.cin"
          else
            CIN=
          fi
          cat <<EOF
add_test( "$BASE" \${CMAKE_CTEST_COMMAND}
  --build-and-test "\${CMAKE_CURRENT_SOURCE_DIR}"
                   "\${CMAKE_CURRENT_BINARY_DIR}"
  --build-makeprogram "\${CMAKE_MAKE_PROGRAM}"
  --build-target $BASE
  --build-no-clean
  --build-run-dir "\${CMAKE_CURRENT_SOURCE_DIR}"
  --test-command sh -c "\${CMAKE_CURRENT_BINARY_DIR}/$BASE$CIN" )
EOF
        fi
      fi
      #add a new line
      echo
    done

  else #======================================================================

    #################
    # SINGLE_SOURCE #
    #################

    target_name=$SOURCE

    echo
    echo
    echo "# Creating entries for target: $target_name"
    #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    cat << 'EOF'
# ############################
EOF
    #-------------------------------------------------------------------------

    for file in `ls *.cc *.cp *.cxx *.cpp *.CPP *.c++ *.C 2> /dev/null | sort` ; do
      all="$all $file"
    done

    # no 'cat' here, as variable substitution required
    echo
    echo "add_executable( ${target_name} ${all} )"
    echo
    echo "add_to_cached_list( CGAL_EXECUTABLE_TARGETS ${target_name} )"
    echo
    echo "# Link the executable to CGAL and third-party libraries"
    LIBS=""
    for comp in ${CGAL_COMPONENTS}; do
        LIBS=$LIBS" CGAL::CGAL_${comp}"
    done
    echo "target_link_libraries(${target_name} PRIVATE CGAL::CGAL${LIBS} )"

  fi # single source or all files #===========================================

  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'
EOF
  #---------------------------------------------------------------------------

echo

}

usage()
{
  echo "Usage: `basename $0` [-s source] [-c cgal-component1:cgal-component2:...] [-b boost-component1:boost-component2:...] [-p] [-o options_file='`pwd`/cgal_cmake_options:$HOME/.cgal_cmake_options_rc'] [-v] [-h]" >&2
  echo >&2
  echo "  -s source If this parameter is given the script will create one single executable for 'source' with all source files; otherwise it creates one executable for each main'ed source." >&2
  echo "  cgal_componentX - must be a valid cgal component, examples are 'Core','ImageIO' ('benchmark', 'symbolic')." >&2
  echo "  boost_componentX - must be a valid boost component, like 'filesystem', 'program_options'." >&2
  echo "  -o options_file - file with PACKAGE, DIRECTORY, CGAL_COMPONENT, and BOOST_COMPONENT directives" >&2
  echo "  -v the version" >&2
  echo "  -h this info screen" >&2
  echo  >&2
}


SINGLE_SOURCE='n'
SOURCE=""

CGAL_COMPONENTS_GIVEN=""
CGAL_COMPONENTS=""

BOOST_COMPONENTS_GIVEN=""
BOOST_COMPONENTS=""

OPTIONS_FILE=`pwd`"/cgal_cmake_options"

if [ ! -e "$OPTIONS_FILE" ]; then
  OPTIONS_FILE="${HOME}/.cgal_cmake_options_rc"
fi

# parse command line arguments
while getopts s:c:b:o:phvt OPT; do
  case "$OPT" in
    s)  SINGLE_SOURCE='y'
        SOURCE=$OPTARG
        if [ "${SOURCE:(-3)}" = ".cc" ]; then
           echo "Error: Source must not end with '.cc'!" >&2
           echo
           usage
           exit 2
        fi
        if [ "${SOURCE:(-3)}" = ".cp" ]; then
           echo "Error: Source must not end with '.cp'!" >&2
           echo
           usage
           exit 2
        fi
        if [ "${SOURCE:(-4)}" = ".cxx" ]; then
           echo "Error: Source must not end with '.cxx'!" >&2
           echo
           usage
           exit 2
        fi
        if [ "${SOURCE:(-4)}" = ".cpp" ]; then
           echo "Error: Source must not end with '.cpp'!" >&2
           echo
           usage
           exit 2
        fi
        if [ "${SOURCE:(-4)}" = ".CPP" ]; then
           echo "Error: Source must not end with '.CPP'!" >&2
           echo
           usage
           exit 2
        fi
        if [ "${SOURCE:(-4)}" = ".c++" ]; then
           echo "Error: Source must not end with '.c++'!" >&2
           echo
           usage
           exit 2
        fi
        if [ "${SOURCE:(-2)}" = ".C" ]; then
           echo "Error: Source must not end with '.C'!" >&2
           echo
           usage
           exit 2
        fi

        ;;

    c)  CGAL_COMPONENTS_GIVEN='y'
        CGAL_COMPONENTS=$OPTARG
        ;;
    b)  BOOST_COMPONENTS_GIVEN='y'
        BOOST_COMPONENTS=$OPTARG
        ;;

    o)  OPTIONS_FILE=$OPTARG
        if [ ! -e "$OPTIONS_FILE" ]; then
          echo "Options-file '$OPTIONS_FILE' does not exist." >&2
          exit 1
        fi
        ;;
    t)  ENABLE_CTEST='y'
        ;;
    h)  usage
        exit 0
        ;;
    v)  echo "`basename $0` version 0.1"
        exit 0
        ;;
    \?) # getopts issues an error message
        usage
        exit 1
        ;;
  esac
done

shift `expr $OPTIND - 1`

#echo "FILE: $OPTIONS_FILE"
#echo "BOOST_COMPONENTS: $BOOST_COMPONENTS"
echo "CGAL_COMPONENTS: $CGAL_COMPONENTS"
#echo "SINGLE_SOURCE: $SINGLE_SOURCE"
#echo "SOURCE: $SOURCE"

OUTPUTFILE=CMakeLists.txt
PROJECT=`basename $PWD`

if [ -f ${OUTPUTFILE} ] ; then
  echo "moving $OUTPUTFILE to ${OUTPUTFILE}.bak ..."
  echo
  mv -f $OUTPUTFILE ${OUTPUTFILE}.bak
fi

create_cmake_script_with_options | tee $OUTPUTFILE

echo
echo "created $OUTPUTFILE in $PWD ..."
