cmake_minimum_required (VERSION 3.12)
cmake_policy (SET CMP0074 NEW)
project (ssc VERSION 0.0.116 LANGUAGES CXX)

set (CMAKE_CXX_STANDARD 17)
set (CMAKE_CXX_STANDARD_REQUIRED True)

# presumes stuff about ssc directory structure ... :-(
set (R ${CMAKE_CURRENT_SOURCE_DIR}/..)
set (H ${R}/heater)
set (S ${R}/sauce)
set (T ${R}/toast)
set (TT ${T}/ssc-test)

set (BV "1.75")

# Debug / Release (https://riptutorial.com/cmake/example/26702/setting-a-release-debug-configuration)
set (CMAKE_CONFIGURATION_TYPES "Debug;Release;MinSizeRel" CACHE STRING "Configs" FORCE)

if (DEFINED CMAKE_BUILD_TYPE)
  set_property (CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_CONFIGURATION_TYPES})
endif ()

set (${PROJ_NAME}_PATH_INSTALL ${D} CACHE PATH "This directory contains an installation path")
set (CMAKE_DEBUG_POSTFIX "d")

add_executable (ssc-test)
add_executable (ssc)

if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
  message ("Only Visual Studios 2015/7/9 are known to build")
  target_compile_definitions (ssc PRIVATE WINDOWS)
  set (D ${R}/..)
endif ()

if (UNIX)
  target_compile_definitions (ssc-test PRIVATE UNIX)
  target_compile_definitions (ssc PRIVATE UNIX)
  set (Boost_USE_STATIC_LIBS ON)
  set (Boost_USE_MULTI_THREADED OFF)

  if (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")

    if (${CMAKE_SYSTEM} MATCHES "OpenBSD-6.8")
      message ("OpenBSD 6.8")
      set (BV "1.67")
      target_compile_definitions (ssc-test PRIVATE NO_PCF_STR)
      target_compile_definitions (ssc PRIVATE OPENBSD O68 NO_PCF_STR NO_PROCESS NO_JSONIC)
    elseif (${CMAKE_SYSTEM} MATCHES "OpenBSD-6.9")
      message ("OpenBSD 6.9")
      set (BV "1.67")
      target_compile_definitions (ssc-test PRIVATE NO_PCF_STR)
      target_compile_definitions (ssc PRIVATE OPENBSD O69 NO_PCF_STR NO_PROCESS NO_JSONIC)
    elseif (${CMAKE_SYSTEM} MATCHES "OpenBSD-7.0")
      message ("OpenBSD 7.0")
      target_compile_definitions (ssc-test PRIVATE NO_PCF_STR)
      target_compile_definitions (ssc PRIVATE OPENBSD O70 NO_PCF_STR NO_PROCESS)
    else ()
      message ("unknown, untested version of OpenBSD")
      target_compile_definitions (ssc PRIVATE OPENBSD NO_PCF_STR NO_PROCESS NO_JSONIC)
    endif ()
  endif ()

  if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
    message ("Linux: only built under Centos 8 amd64 and Ubuntu Server 20.10 amd64")
    set (BV "1.67")
    target_compile_definitions (ssc PRIVATE LINUX NO_JSONIC)
  endif ()

  if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
    link_directories (${BOOST_LIBRARYDIR} ${ICU_PATH}/lib)
    if (${CMAKE_SYSTEM} MATCHES "Darwin-20")
      message ("MacOS Big Sur")
      target_compile_definitions (ssc PRIVATE BIG_SUR MACOS)
    elseif (${CMAKE_SYSTEM} MATCHES "Darwin-19")
      set (BV "1.67")
      message ("MacOS Catalina")
      target_compile_definitions (ssc PRIVATE CATALINA MACOS NO_JSONIC)
    elseif (${CMAKE_SYSTEM} MATCHES "Darwin-18")
      set (BV "1.67")
      message ("MacOS Mojave")
      target_compile_definitions (ssc PRIVATE MOJAVE MACOS NO_JSONIC)
    elseif (${CMAKE_SYSTEM} MATCHES "Darwin-17")
      set (BV "1.67")
      message ("MacOS High Sierra")
      target_compile_definitions (ssc-test PRIVATE FUDDYDUDDY)
      target_compile_definitions (ssc PRIVATE HIGH_SIERRA FUDDYDUDDY MACOS NO_JSONIC)
    else ()
      message ("unknown, untested MacOS")
      target_compile_definitions (ssc PRIVATE MACOS)
    endif ()
  endif ()

  set (D "~/bin")
endif ()

find_package (Boost ${BV} REQUIRED COMPONENTS system date_time filesystem locale program_options)
find_package (ICU 60.0 REQUIRED COMPONENTS dt in io tu uc)
find_package (Iconv REQUIRED)

# better to list the build files in one place (here) rather than litter all the source directories with a gadzillion untidy wee files
target_sources (ssc-test PRIVATE ${S}/test/ssc-test.cpp ${H}/main/version.h ${H}/feedback/nitnames.h ${S}/feedback/nitnames.cpp)
target_sources (ssc PRIVATE
    ${H}/attribute/attr.h ${H}/attribute/attribute.h ${H}/attribute/attribute_classes.h ${H}/attribute/attributes.h ${H}/attribute/avm.h
            ${H}/attribute/avm_data.h ${H}/attribute/namespace.h
        ${H}/css/css.h ${H}/css/css_cache.h
        ${H}/element/elem.h ${H}/element/element.h ${H}/element/element_attribute.h ${H}/element/element_classes.h ${H}/element/parentage.h
            ${H}/element/state.h
        ${H}/feedback/nit.h ${H}/feedback/nitnames.h ${H}/feedback/nitout.h ${H}/feedback/nitpick.h
        ${H}/icu/charset.h ${H}/icu/converter.h ${H}/icu/wrapper.h
        ${H}/main/abort.h ${H}/main/args.h ${H}/main/context.h ${H}/main/include.h ${H}/main/options.h ${H}/main/standard.h ${H}/main/version.h
        ${H}/microdata/microdata_export.h ${H}/microdata/microdata_itemid.h ${H}/microdata/microdata_itemprop.h ${H}/microdata/microdata_itemscope.h
            ${H}/microdata/microdata_itemtype.h
        ${H}/microformat/connection.h ${H}/microformat/family.h ${H}/microformat/field.h ${H}/microformat/microformat.h
            ${H}/microformat/microformat_classes.h ${H}/microformat/microformat_constructor.h ${H}/microformat/microformat_export.h
            ${H}/microformat/microformat_export_rel.h ${H}/microformat/microformat_properties.h ${H}/microformat/microformats.h
            ${H}/microformat/microformats_ptr.h ${H}/microformat/prop.h ${H}/microformat/property.h ${H}/microformat/property_classes.h
            ${H}/microformat/property_value.h ${H}/microformat/sibling.h
        ${H}/parser/html_version.h ${H}/parser/jsonic.h ${H}/parser/parse_abb.h ${H}/parser/parse_attribute.h ${H}/parser/parse_attributes.h
            ${H}/parser/parse_bra_ket.h ${H}/parser/parse_bras_ket.h ${H}/parser/parse_css.h ${H}/parser/parse_element.h ${H}/parser/parse_elements.h
            ${H}/parser/parse_ssi.h ${H}/parser/pattern.h ${H}/parser/text.h ${H}/parser/text-data.h ${H}/parser/xhtml_xml.h
        ${H}/rdf/rdf.h ${H}/rdf/rdfa_prop.h ${H}/rdf/rdfa_type.h
        ${H}/schema/schema_hierarchy.h ${H}/schema/schema_name.h ${H}/schema/schema_property.h ${H}/schema/schema_structure.h ${H}/schema/schema_type.h
            ${H}/schema/schema_version.h
        ${H}/stats/stats.h ${H}/stats/stats0.h ${H}/stats/stats1.h ${H}/stats/stats2.h ${H}/stats/stats3.h ${H}/stats/stats4.h ${H}/stats/stats_impl.h
        ${H}/symbol/nstr.h ${H}/symbol/symbol.h ${H}/symbol/symbol_entry.h ${H}/symbol/symbol_key.h ${H}/symbol/symbol_store.h ${H}/symbol/symbol_table.h
        ${H}/type/enum.h ${H}/type/reldef.h ${H}/type/sz.h ${H}/type/type.h ${H}/type/type_1.h ${H}/type/type_2.h ${H}/type/type_3.h ${H}/type/type_4.h
            ${H}/type/type_aria.h ${H}/type/type_autocomplete.h ${H}/type/type_base.h ${H}/type/type_case.h ${H}/type/type_charset.h ${H}/type/type_class.h
            ${H}/type/type_colour.h ${H}/type/type_cookie.h ${H}/type/type_core.h ${H}/type/type_csp.h ${H}/type/type_currency.h ${H}/type/type_enum.h
            ${H}/type/type_enum_vec.h ${H}/type/type_httpequiv.h ${H}/type/type_lang.h ${H}/type/type_master.h ${H}/type/type_media.h
            ${H}/type/type_metaname.h ${H}/type/type_mime.h ${H}/type/type_rdf.h ${H}/type/type_reals.h ${H}/type/type_rel.h ${H}/type/type_relational.h
            ${H}/type/type_time.h ${H}/type/type_url.h ${H}/type/type_van.h ${H}/type/type_basic.h ${H}/type/type_id.h ${H}/type/type_layout.h
            ${H}/type/type_math.h ${H}/type/type_measure.h ${H}/type/type_microdata.h ${H}/type/type_microformat.h ${H}/type/type_misc.h
            ${H}/type/type_numeric.h ${H}/type/type_svg.h ${H}/type/type_varied.h ${H}/type/type_xmlns.h
        ${H}/url/url.h ${H}/url/url_parameters.h ${H}/url/url_protocol.h ${H}/url/url_sanitise.h ${H}/url/url_scheme.h ${H}/url/url_schemes.h
        ${H}/utility/bigvector.h ${H}/utility/byteorder.h ${H}/utility/common.h ${H}/utility/filesystem.h ${H}/utility/lexical.h ${H}/utility/quote.h
            ${H}/utility/tuple.h
        ${H}/webmention/hook.h ${H}/webmention/irt.h ${H}/webmention/webmention.h ${H}/webmention/webmentions.h
        ${H}/webpage/corpus.h ${H}/webpage/crosslink.h ${H}/webpage/directory.h ${H}/webpage/external.h ${H}/webpage/fileindex.h ${H}/webpage/headers.h
            ${H}/webpage/id.h ${H}/webpage/page.h ${H}/webpage/root.h
        ${S}/attribute/attr.cpp ${S}/attribute/attribute_constructor.cpp ${S}/attribute/attributes.cpp ${S}/attribute/avm.cpp ${S}/attribute/avm_data_a.cpp
             ${S}/attribute/avm_data_b.cpp ${S}/attribute/avm_data_c.cpp ${S}/attribute/avm_data_d.cpp ${S}/attribute/avm_data_e.cpp ${S}/attribute/avm_data_f.cpp
             ${S}/attribute/avm_data_g.cpp ${S}/attribute/avm_data_h.cpp ${S}/attribute/avm_data_i.cpp ${S}/attribute/avm_data_k.cpp ${S}/attribute/avm_data_l.cpp
             ${S}/attribute/avm_data_m.cpp ${S}/attribute/avm_data_n.cpp ${S}/attribute/avm_data_o.cpp ${S}/attribute/avm_data_p.cpp ${S}/attribute/avm_data_q.cpp
             ${S}/attribute/avm_data_r.cpp ${S}/attribute/avm_data_s.cpp ${S}/attribute/avm_data_t.cpp ${S}/attribute/avm_data_u.cpp ${S}/attribute/avm_data_v.cpp
             ${S}/attribute/avm_data_w.cpp ${S}/attribute/avm_data_x.cpp ${S}/attribute/avm_data_cc.cpp ${S}/attribute/avm_data_dc.cpp
             ${S}/attribute/avm_data_dct_a.cpp ${S}/attribute/avm_data_dct_b.cpp ${S}/attribute/avm_data_rdf.cpp ${S}/attribute/namespace.cpp
        ${S}/css/css.cpp ${S}/css/css_cache.cpp
        ${S}/element/elem.cpp ${S}/element/element.cpp ${S}/element/element_abcd.cpp ${S}/element/element_aria.cpp ${S}/element/element_attributes.cpp
            ${S}/element/element_classes.cpp ${S}/element/element_efghi.cpp ${S}/element/element_examine.cpp ${S}/element/element_input.cpp
            ${S}/element/element_jkl.cpp ${S}/element/element_microdata.cpp ${S}/element/element_microformats.cpp ${S}/element/element_mno.cpp
            ${S}/element/element_pqr.cpp ${S}/element/element_rdfa.cpp ${S}/element/element_s.cpp ${S}/element/element_tuvwxyz.cpp ${S}/element/parentage.cpp
            ${S}/element/state.cpp
        ${S}/feedback/nit.cpp ${S}/feedback/nitnames.cpp ${S}/feedback/nitout.cpp ${S}/feedback/nitpick.cpp
        ${S}/icu/charset.cpp ${S}/icu/converter.cpp ${S}/icu/wrapper.cpp
        ${S}/main/abort.cpp ${S}/main/context.cpp ${S}/main/options.cpp ${S}/main/ssc.cpp ${S}/main/standard.cpp ${S}/main/version.cpp
        ${S}/microdata/microdata_export.cpp ${S}/microdata/microdata_itemid.cpp ${S}/microdata/microdata_itemprop.cpp ${S}/microdata/microdata_itemscope.cpp
            ${S}/microdata/microdata_itemtype.cpp
        ${S}/microformat/family.cpp ${S}/microformat/field.cpp ${S}/microformat/microformat_constructor.cpp ${S}/microformat/microformat_export.cpp
            ${S}/microformat/microformats.cpp ${S}/microformat/property_value.cpp ${S}/microformat/sibling.cpp
        ${S}/parser/html_version.cpp ${S}/parser/jsonic.cpp ${S}/parser/parse_attribute.cpp ${S}/parser/parse_attributes.cpp ${S}/parser/parse_bra_ket.cpp
            ${S}/parser/parse_bras_ket.cpp ${S}/parser/parse_css.cpp ${S}/parser/parse_element.cpp ${S}/parser/parse_elements.cpp ${S}/parser/parse_ssi.cpp
            ${S}/parser/pattern.cpp ${S}/parser/text.cpp ${S}/parser/text-data.cpp ${S}/parser/xhtml_xml.cpp
        ${S}/rdf/rdf.cpp ${S}/rdf/rdfa_prop.cpp ${S}/rdf/rdfa_type.cpp
        ${S}/schema/schema_hierarchy.cpp ${S}/schema/schema_name.cpp ${S}/schema/schema_property.cpp ${S}/schema/schema_structure.cpp
            ${S}/schema/schema_type.cpp ${S}/schema/schema_version.cpp
        ${S}/stats/stats.cpp ${S}/stats/stats_impl.cpp
        ${S}/symbol/nstr.cpp ${S}/symbol/symbol.cpp
        ${S}/type/type.cpp ${S}/type/type_aria.cpp ${S}/type/type_autocomplete.cpp ${S}/type/type_charset.cpp ${S}/type/type_class.cpp ${S}/type/type_colour.cpp
            ${S}/type/type_core.cpp ${S}/type/type_csp.cpp ${S}/type/type_currency.cpp ${S}/type/type_d.cpp ${S}/type/type_enum.cpp ${S}/type/type_httpequiv.cpp
            ${S}/type/type_lang.cpp ${S}/type/type_media.cpp ${S}/type/type_metaname.cpp ${S}/type/type_mime.cpp ${S}/type/type_numeric.cpp
            ${S}/type/type_paint.cpp ${S}/type/type_rdf.cpp ${S}/type/type_reals.cpp ${S}/type/type_rel.cpp ${S}/type/type_sgml.cpp
            ${S}/type/type_svg_feature.cpp ${S}/type/type_time.cpp ${S}/type/type_transform.cpp ${S}/type/type_url.cpp ${S}/type/type_varied.cpp
            ${S}/type/type_xmlns.cpp
        ${S}/url/url.cpp ${S}/url/url_parameters.cpp ${S}/url/url_protocol.cpp ${S}/url/url_sanitise.cpp ${S}/url/url_scheme.cpp
        ${S}/utility/byteorder.cpp ${S}/utility/common.cpp ${S}/utility/filesystem.cpp ${S}/utility/quote.cpp
        ${S}/webmention/hook.cpp ${S}/webmention/irt.cpp ${S}/webmention/webmention.cpp ${S}/webmention/webmentions.cpp
        ${S}/webpage/corpus.cpp ${S}/webpage/crosslink.cpp ${S}/webpage/directory.cpp ${S}/webpage/external.cpp ${S}/webpage/fileindex.cpp
            ${S}/webpage/headers.cpp ${S}/webpage/id.cpp ${S}/webpage/page.cpp ${S}/webpage/root.cpp
)

target_include_directories (ssc-test PRIVATE ${H} ${BOOST_INCLUDE_DIRS})
target_include_directories (ssc PRIVATE ${H} ${BOOST_INCLUDE_DIRS} ${ICU_INCLUDE_DIRS})

target_compile_definitions (ssc-test PRIVATE SSC_TEST)

if (${CMAKE_BUILD_TYPE} MATCHES "Debug")
  message ("debug")
  target_compile_definitions (ssc-test PRIVATE _DEBUG)
  target_compile_definitions (ssc PRIVATE _DEBUG)
  target_compile_options (ssc-test PRIVATE "-g;-O0;-fvisibility=hidden;-fvisibility-inlines-hidden;-Wall;-Wextra;-Wno-dangling-else;-Wno-write-strings;-Wno-implicit-fallthrough;-Wno-misleading-indentation;-Wno-unused-result;-Wno-deprecated-declarations")
  target_compile_options (ssc PRIVATE "-g;-O0;-fvisibility=hidden;-fvisibility-inlines-hidden;-Wall;-Wextra;-Wno-dangling-else;-Wno-write-strings;-Wno-implicit-fallthrough;-Wno-misleading-indentation;-Wno-deprecated-declarations")
else ()
  message ("release")
  target_compile_definitions (ssc-test PRIVATE NDEBUG)
  target_compile_definitions (ssc PRIVATE NDEBUG)
  if (${CMAKE_BUILD_TYPE} MATCHES "MinSizeRel")
    target_compile_options (ssc-test PRIVATE "-Os;-fvisibility=hidden;-fvisibility-inlines-hidden;-Wall;-Wextra;-Wno-dangling-else;-Wno-write-strings;-Wno-implicit-fallthrough;-Wno-misleading-indentation;-Wno-unused-result;-Wno-unused-parameter;-Wno-deprecated-declarations")
    target_compile_options (ssc PRIVATE "-Os;-fvisibility=hidden;-fvisibility-inlines-hidden;-Wall;-Wextra;-Wno-dangling-else;-Wno-write-strings;-Wno-implicit-fallthrough;-Wno-misleading-indentation;-Wno-unused-parameter;-Wno-deprecated-declarations")
  else ()
    target_compile_options (ssc-test PRIVATE "-O3;-fvisibility=hidden;-fvisibility-inlines-hidden;-Wall;-Wextra;-Wno-dangling-else;-Wno-write-strings;-Wno-implicit-fallthrough;-Wno-misleading-indentation;-Wno-unused-result;-Wno-unused-parameter;-Wno-deprecated-declarations")
    target_compile_options (ssc PRIVATE "-O3;-fvisibility=hidden;-fvisibility-inlines-hidden;-Wall;-Wextra;-Wno-dangling-else;-Wno-write-strings;-Wno-implicit-fallthrough;-Wno-misleading-indentation;-Wno-unused-parameter;-Wno-deprecated-declarations")
  endif ()
endif ()

target_link_libraries (ssc-test PRIVATE Boost::filesystem)
target_link_libraries (ssc-test PRIVATE pthread)

target_link_libraries (ssc PRIVATE Boost::system)
target_link_libraries (ssc PRIVATE Boost::date_time)
target_link_libraries (ssc PRIVATE Boost::filesystem)
target_link_libraries (ssc PRIVATE Boost::program_options)
target_link_libraries (ssc PRIVATE Boost::locale)
target_link_libraries (ssc PRIVATE pthread)
target_link_libraries (ssc PRIVATE ${ICU_LIBRARIES})

install (TARGETS ssc-test DESTINATION ${D})
install (TARGETS ssc DESTINATION ${D})

enable_testing ()

add_test (NAME toasty_toast COMMAND ssc-test -d -i ${TT}/output.txt ${TT}/input.spec)
add_test (NAME toast COMMAND ssc-test -v -f ${TT}/ssc.lst)
