#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

#
# Build the C client for the HTrace distributed tracing system.
#

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
set(CMAKE_BUILD_TYPE, Release)  # Default to release builds

# Define "make check" as an alias for "make test."
add_custom_target(check COMMAND ctest)
enable_testing()

if (WIN32)
    MESSAGE(FATAL_ERROR "Windows support is not yet available.")
else() # UNIX
    set(CMAKE_C_FLAGS "-g ${CMAKE_C_FLAGS} -Wall -O2 -fno-strict-aliasing")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_REENTRANT") # Enable pthreads.
    if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
        # _GNU_SOURCE is needed to see all the glibc definitions.
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_GNU_SOURCE")
        # Use the 64-bit forms of off_t, etc.
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64")
    endif()
endif()

INCLUDE(CheckCSourceCompiles)
CHECK_C_SOURCE_COMPILES("int main(void) { static __thread int i = 0; return 0; }" HAVE_IMPROVED_TLS)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/util/build.h.cmake ${CMAKE_BINARY_DIR}/util/build.h)

get_filename_component(HTRACED_TOOL_ABSPATH "../../htrace-htraced/go/build/htracedTool" ABSOLUTE)
get_filename_component(HTRACED_ABSPATH "../../htrace-htraced/go/build/htraced" ABSOLUTE)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/test/test_config.h.cmake ${CMAKE_BINARY_DIR}/test/test_config.h)

find_package(PkgConfig)
pkg_check_modules(PC_JSON-C QUIET json-c)
find_path(JSON_C_INCLUDE_DIR "json.h"
    HINTS ${JSON_C_PREFIX} ${PC_JSON-C_INCLUDEDIR} ${PC_JSON-C_INCLUDE_DIRS} PATH_SUFFIXES json-c json)
find_library(JSON_C_LIBRARY NAMES json-c json libjson
    HINTS ${JSON_C_PREFIX}${PC_JSON-C_LIBDIR} ${PC_JSON-C_LIBRARY_DIRS})
IF(JSON_C_INCLUDE_DIR AND JSON_C_LIBRARY)
ELSE(JSON_C_INCLUDE_DIR AND JSON_C_LIBRARY)
    MESSAGE(FATAL_ERROR "Failed to find libjson-c. Try installing libjson-c with apt-get or yum, or install it manually from http://oss.metaparadigm.com/json-c/")
ENDIF(JSON_C_INCLUDE_DIR AND JSON_C_LIBRARY)

include_directories(${CMAKE_BINARY_DIR}
                    ${CMAKE_SOURCE_DIR}
                    ${JSON_C_INCLUDE_DIR})

if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
    set(RAND_SRC "util/rand_linux.c")
else()
    set(RAND_SRC "util/rand_posix.c")
endif()

set(SRC_ALL
    ${RAND_SRC}
    core/conf.c
    core/htracer.c
    core/scope.c
    core/span.c
    core/span_id.c
    receiver/hrpc.c
    receiver/htraced.c
    receiver/local_file.c
    receiver/noop.c
    receiver/receiver.c
    sampler/always.c
    sampler/never.c
    sampler/prob.c
    sampler/sampler.c
    util/cmp.c
    util/cmp_util.c
    util/htable.c
    util/log.c
    util/tracer_id.c
    util/string.c
    util/terror.c
    util/time.c
)

set(DEPS_ALL pthread)
IF (CMAKE_SYSTEM_NAME MATCHES "Linux")
  set(DEPS_ALL ${DEPS_ALL} rt)
ENDIF()

# The unit test version of the library, which exposes all symbols.
add_library(htrace_test STATIC
    ${SRC_ALL}
    test/mini_htraced.c
    test/span_table.c
    test/span_util.c
    test/temp_dir.c
    test/test.c
)
target_link_libraries(htrace_test ${DEPS_ALL} ${JSON_C_LIBRARY})

# Hide all symbols by default.  Only the symbols we specifically mark as
# visible should be accessable by the library user.  This should avoid
# conflicts between our function and global variable names and those of
# the host program.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")

# The production version of the library, which exposes only the public API.
add_library(htrace SHARED ${SRC_ALL})
target_link_libraries(htrace ${DEPS_ALL})
# Set version 4.2.0
set(HTRACE_VERSION_MAJOR "4")
set(HTRACE_VERSION_MINOR "2")
set(HTRACE_VERSION_PATCH "0")
set(HTRACE_VERSION_STRING
    "${HTRACE_VERSION_MAJOR}.${HTRACE_VERSION_MINOR}.${HTRACE_VERSION_PATCH}")
set_target_properties(htrace PROPERTIES
    VERSION ${HTRACE_VERSION_STRING}
    SOVERSION ${HTRACE_VERSION_MAJOR})

macro(add_utest utest)
    add_executable(${utest}
        ${ARGN}
    )
    target_link_libraries(${utest} htrace_test)
    add_test(${utest} ${CMAKE_CURRENT_BINARY_DIR}/${utest} ${utest})
endmacro(add_utest)

add_utest(cmp_util-unit
    test/cmp_util-unit.c
)

add_utest(conf-unit
    test/conf-unit.c
)

add_utest(htable-unit
    test/htable-unit.c
)

add_utest(htraced_rcv-unit
    test/htraced_rcv-unit.c
    test/rtest.c
)

add_executable(linkage-unit test/linkage-unit.c)
target_link_libraries(linkage-unit htrace dl)
add_test(linkage-unit ${CMAKE_CURRENT_BINARY_DIR}/linkage-unit linkage-unit)

add_utest(local_file_rcv-unit
    test/local_file_rcv-unit.c
    test/rtest.c
)

add_utest(local_file_rcvpp-unit
    test/local_file_rcv-unit.c
    test/rtestpp.cc
)

add_utest(log-unit
    test/log-unit.c
)

add_utest(mini_htraced-unit
    test/mini_htraced-unit.c
)

add_utest(tracer_id-unit
    test/tracer_id-unit.c
)

if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
    add_utest(rand_linux-unit
        test/rand-unit.c
        util/rand_linux.c
    )
endif()
add_utest(rand_posix-unit
    test/rand-unit.c
    util/rand_posix.c
)

add_utest(sampler-unit
    test/sampler-unit.c
)

add_utest(span-unit
    test/span-unit.c
)

add_utest(span_id-unit
    test/span_id-unit.c
)

add_utest(string-unit
    test/string-unit.c
)

add_utest(temp_dir-unit
    test/temp_dir-unit.c
)

add_utest(time-unit
    test/time-unit.c
)

# Install libhtrace.so and htrace.h.
# These are the only build products that external users can consume.
install(TARGETS htrace DESTINATION lib)
install(FILES ${CMAKE_SOURCE_DIR}/core/htrace.h DESTINATION include)
