#-------------------------------------------------------------------------------
# Parametric SCC based Model Checking
#  
# This is a stand-alone tool which performs model checking
# for parametric discrete-time Markov Chains (PDTMCs).
# 
# Copyright (c) 2013 RWTH Aachen University.
# Authors: Florian Corzilius, Nils Jansen, Matthias Volk
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see
# http://www.gnu.org/licenses/gpl.html.
# 
# 
# Main Contact:
# 
# Nils Jansen
# Theory of Hybrid Systems
# RWTH Aachen
# 52056 Aachen
# Germany
# nils.jansen@cs.rwth-aachen.de
#-------------------------------------------------------------------------------

# cmake file for param_sccmc
project(param_sccmc)

cmake_minimum_required(VERSION 2.6)

option(USE_LOGLIB     "Use llog4cplus logging library" OFF)
option(USE_POLY_MANAGEMENT "Use polynomial management" OFF)
option(STATICLIB_SWITCH "Compile a statically linked version of the library." OFF)

#Static linking
if(${STATICLIB_SWITCH} STREQUAL "ON")
  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -Wl,--whole-archive -ldl -Wl,--no-whole-archive -Wl,-Bstatic -lm" )
  set(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.so")
endif()

# generate parser for prism
find_package(BISON)
find_package(FLEX)
BISON_TARGET(Parser src/io/param/prismparser/PRISM.ypp ${CMAKE_CURRENT_SOURCE_DIR}/src/io/param/prismparser/PRISM.tab.cpp COMPILE_FLAGS "-p PRISM")
FLEX_TARGET(Scanner src/io/param/prismparser/PRISM.l ${CMAKE_CURRENT_SOURCE_DIR}/src/io/param/prismparser/PRISM.yy.cpp COMPILE_FLAGS "-PPRISM")
ADD_FLEX_BISON_DEPENDENCY(Scanner Parser)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})

# add source files here
set(param_sccmc_SRCS
    	src/defines.h
    	src/typedefs.h
	
	src/data/GraphTypes.cpp
	src/LocalLogging.cpp
	src/data/Path.cpp
	src/data/Polynomial2.cpp
	src/data/Factorization.cpp
	src/data/ParametricSets.cpp
	src/data/Cancellator2.cpp
	src/data/Rational.cpp
	src/data/AbstractParameter.cpp
	src/data/Parameters.cpp
	src/data/Constraint.cpp
	src/io/param/prismparser/Util.cpp
	src/io/param/prismparser/Expr.cpp
	src/io/param/prismparser/AST.cpp
	src/io/param/prismparser/PRISMParser.cpp
	src/io/param/prismparser/PRISM.tab.cpp
	src/io/param/prismparser/PRISM.yy.cpp
	src/io/param/prismparser/Model.cpp
	src/io/param/prismparser/Node.cpp
	src/io/param/prismparser/Property.cpp
	src/io/param/prismparser/Substitutor.cpp
	src/io/param/prismparser/System.cpp
	src/io/param/prismparser/Reward.cpp
	src/io/param/model2x/Model2X.cpp
	src/io/param/model2x/expr2lua.cpp
	src/io/param/model2x/Model2XError.cpp
	src/io/param/model2x/ValueCompute.cpp
	src/io/param/model2x/InitStatesComp.cpp
	src/io/param/rationalFunction/Polynomial.cpp
	src/io/param/rationalFunction/Geobucket.cpp
	src/io/param/rationalFunction/RationalFunction.cpp
	src/io/param/rationalFunction/RationalCmp.cpp
	src/io/param/rationalFunction/Base.cpp
	src/io/param/rationalFunction/Cancellator.cpp
	src/io/param/parametric/ModelExplorer.cpp
	src/io/param/parametric/Model2XExplorer.cpp
	src/io/param/parametric/PMM.cpp
	src/io/param/parametric/PMC.cpp
	src/io/param/parametric/SPMC.cpp
	src/io/param/parametric/PMDP.cpp
	src/io/param/parametric/SPMDP.cpp
	src/io/param/parametric/ExprToNumber.cpp
	src/io/Configuration.cpp
	src/io/pugixml/pugixml.cpp
	src/io/input/XMLReader.cpp
	src/io/input/PrismReader.cpp
	src/io/IOWrapper.cpp
	src/mc/ModelChecker.cpp
	src/mc/SCC_MC.cpp
	src/mc/State_Elim.cpp
	src/io/Main.cpp
)

# tells cmake to compile an executable from the srcs
add_executable(param_sccmc ${param_sccmc_SRCS} ${BISON_Parser_OUTPUTS} ${FLEX_Scanner_OUTPUTS})

# path to find own modules
set( CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake )

# add required boost libs here
find_package(Boost COMPONENTS program_options system filesystem REQUIRED)
include_directories(${Boost_INCLUDE_DIR})
set(LIBS ${LIBS}
    ${Boost_PROGRAM_OPTIONS_LIBRARY}
    ${Boost_FILESYSTEM_LIBRARY}
    ${Boost_SYSTEM_LIBRARY}
)

# extra logger libs if requested
if(USE_LOGLIB)
    add_definitions(-DUSE_LOGLIB)
    find_package(Log4cplus REQUIRED)
    include_directories(${LOG4CPLUS_INCLUDE_DIRS})
    set(LIBS ${LIBS} ${LOG4CPLUS_LIBRARIES})
endif(USE_LOGLIB)

add_definitions(-DUSE_PARAMETRIC)
        
#CLN
find_package(CLN 1.2.2 REQUIRED)
include_directories(${CLN_INCLUDE_DIRS})
set(LIBS ${LIBS} ${cln_LIBRARY_DIRS})
        
#Polynomial management
if (USE_POLY_MANAGEMENT)
	add_definitions(-DUSE_POLY_MANAGEMENT)
endif(USE_POLY_MANAGEMENT)
        
#GiNaC
find_package(GiNaC REQUIRED)
include_directories(${GINAC_INCLUDE_DIRS})
set(LIBS ${LIBS} ${GINAC_LIBRARIES})
        
#GMP
find_package(GMP REQUIRED)
include_directories(${GMP_INCLUDE_DIRS})
set(LIBS ${LIBS} ${GMP_LIBRARIES})

find_package(GMPXX REQUIRED)
include_directories(${GMPXX_INCLUDE_DIRS})
set(LIBS ${LIBS} ${GMPXX_LIBRARIES})
        
#Luajit
find_package(LUAJIT REQUIRED)
include_directories(${LUAJIT_INCLUDE_DIRS})
set(LIBS ${LIBS} ${LUAJIT_LIBRARIES})

# Set "Release" as default build type
if (NOT CMAKE_BUILD_TYPE)
	message(STATUS "No build type selected, default to Release")
	set(CMAKE_BUILD_TYPE "Release")
endif()

# use CMake's "Debug" target if DEBUGGING is set, else "Release"
# I'm not sure what the exact differences are, but it's probably
# what we want (e.g., optimization level etc.)
if(CMAKE_BUILD_TYPE MATCHES DEBUG OR CMAKE_BUILD_TYPE MATCHES Debug)
    add_definitions(-DDEBUGGING)

    # while we're at it, let's set Wall
    if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
    else(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
        message("DEBUGGING was set but the compiler is unknown. Cannot set -Wall.")
    endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
else (CMAKE_BUILD_TYPE MATCHES DEBUG OR CMAKE_BUILD_TYPE MATCHES Debug)
    add_definitions(-DNDEBUG)
endif(CMAKE_BUILD_TYPE MATCHES DEBUG OR CMAKE_BUILD_TYPE MATCHES Debug)

# pass profiling args
# (I have no idea what this does (well something about gcc's
# debug code), just taken from the old automake file)
if(PROFILING)
    if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg -g")
    else(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
        message("PROFILING was set but the compiler is unknown. Cannot set -pg -g.")
    endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
endif(PROFILING)

# set C standard
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
    message("Unknown compiler. Cannot set -std=c++11.")
endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)

#Static linking
if(${STATICLIB_SWITCH} STREQUAL "ON")
  set_target_properties(param_sccmc PROPERTIES LINK_SEARCH_START_STATIC 1)
  set_target_properties(param_sccmc PROPERTIES LINK_SEARCH_END_STATIC 1)
endif()

# link required libs
target_link_libraries(param_sccmc ${LIBS})
