# Copyright (C) 2009 David Sugar, Tycho Softworks
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# This is a simplified build system for GNU uCommon.  In particular, it
# offers limited cmodel linkage support, at least for mingw32 support (and
# probably visual c 6 also).  If one really needs to do such things outside
# these use cases, it is suggested to continue using the existing autotools 
# configure script driven build environment instead.  Mostly the cmake one is 
# meant for generating project files for those working with IDE's to do 
# otherwise generic builds of the library and supporting applications.

cmake_minimum_required(VERSION 2.6)
PROJECT(ucommon)
set (VERSION 2.0.7)
set (SOVERSION 2)

MESSAGE( STATUS "Configuring GNU ucommon ${VERSION}...")
include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckIncludeFiles)

# set to true for debug and trace during CMakeLists development
set(CMAKE_VERBOSE_MAKEFILE FALSE)
 
# add module path of project if it exists...
if (EXISTS "${CMAKE_SOURCE_DIR}/inc/")
	set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/inc/")
endif()

include (inc/ucommon.cmake)

find_package(Threads)
if (CMAKE_HAVE_PTHREAD_H)
	set(HAVE_PTHREAD_H TRUE)
endif()
set (UCOMMON_LIBS ${UCOMMON_LIBS} ${CMAKE_THREAD_LIBS_INIT} ${WITH_LDFLAGS}) 

if ((WIN32 AND CMAKE_COMPILER_IS_GNUCXX) OR MINGW OR MSYS)
	set (UCOMMON_LIBS --enable-stdcall-fixup ${UCOMMON_LIBS} mingwex mingw32)
endif()

if (WIN32 OR MINGW OR MSYS)
	set (UCOMMON_LIBS ${UCOMMON_LIBS} ws2_32 wsock32 kernel32)
endif()

if(WITH_NOSTDLIB AND UNIX)
	set(UCOMMON_LIBS c)
endif()

if(WITH_NOSTDLIB AND CMAKE_COMPILER_IS_GNUCXX)
	check_library_exists(gcc __modsi3 "" HAVE_GCC_LIB)
	if(HAVE_GCC_LIB)
			set(UCOMMON_LIBS ${UCOMMON_LIBS} gcc)
	endif()
endif()

if(UNIX OR MSYS OR MINGW OR CYGWIN)
	check_library_exists(dl dlopen "" HAVE_DL_LIB)
	if (HAVE_DL_LIB)
		set (UCOMMON_LIBS ${UCOMMON_LIBS} dl)
	else()
		check_library_exists(compat dlopen "" HAVE_COMPAT_LIB)
		if(HAVE_COMPAT_LIB)
			set (UCOMMON_LIBS ${UCOMMON_LIBS} compat)
		endif()
	endif()

	check_library_exists(dld shl_load "" HAVE DLD_LIB)
	if (HAVE_DLD_LIB)
		set (UCOMMON_LIBS ${UCOMMON_LIBS} dld)
	endif()

	check_library_exists(socket socket "" HAVE_SOCKET_LIB)
	if (HAVE_SOCKET_LIB)
		set (UCOMMON_LIBS ${UCOMMON_LIBS} socket)
	endif()

	check_library_exists(posix4 sem_wait "" HAVE_POSIX4_LIB)
	if (HAVE_POSIX4_LIB)
		set(UCOMMON_LIBS ${UCOMMON_LIBS} posix4)
	endif()

	check_library_exists(rt clock_gettime "" HAVE_RT_LIB)
	if (HAVE_RT_LIB)
		set(UCOMMON_LIBS ${UCOMMON_LIBS} rt)
	endif()
endif()

set (CMAKE_REQUIRED_LIBRARIES ${UCOMMON_LIBS})
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
check_function_exists(socketpair HAVE_SOCKETPAIR)
check_function_exists(inet_ntop HAVE_INET_NTOP)
check_function_exists(gethostbyname2 HAVE_GETHOSTBYNAME2)
check_function_exists(stricmp HAVE_STRICMP)
check_function_exists(stristr HAVE_STRISTR)
check_function_exists(sysconf HAVE_SYSCONF)
check_function_exists(posix_memalign HAVE_POSIX_MEMALIGN)
check_function_exists(dlopen HAVE_DLOPEN)
check_function_exists(shl_open HAVE_SHL_OPEN)
check_function_exists(pthread_condattr_setclock HAVE_PTHREAD_CONDATTR_SETCLOCK)
check_function_exists(pthread_setconcurrency HAVE_PTHREAD_SETCONCURRENCY)
check_function_exists(pthread_yield HAVE_PTHREAD_YIELD)
check_function_exists(pthread_yield_np HAVE_PTHREAD_YIELD_NP)
check_function_exists(pthread_delay HAVE_PTHREAD_DELAY)
check_function_exists(pthread_delay_np HAVE_PTHREAD_DELAY_NP)
check_function_exists(pthread_setschedprio HAVE_PTHREAD_SETSCHEDPRIO)
check_function_exists(ftok HAVE_FTOK)
check_function_exists(shm_open HAVE_SHM_OPEN)
check_function_exists(localtime_r HAVE_LOCALTIME_R)
check_function_exists(nanosleep HAVE_NANOSLEEP)
check_function_exists(clock_nanosleep HAVE_CLOCK_NANOSLEEP)
check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
check_function_exists(posix_fadvise HAVE_POSIX_FADVISE)
check_function_exists(posixtime HAVE_POSIXTIME)

check_include_files(sys/stat.h HAVE_SYS_STAT_H)
check_include_files(strings.h HAVE_STRINGS_H)
check_include_files(stdlib.h HAVE_STDLIB_H)
check_include_files(string.h HAVE_STRING_H)
check_include_files(memory.h HAVE_MEMORY_H)
check_include_files(inttypes.h HAVE_INTTYPES_H)
check_include_files(dlfcn.h HAVE_DLFCN_H)
check_include_files(stdint.h HAVE_STDINT_H)
check_include_files(poll.h HAVE_POLL_H)
check_include_files(sys/mman.h HAVE_SYS_MMAN_H)
check_include_files(sys/shm.h HAVE_SYS_SHM_H)
check_include_files(sys/poll.h HAVE_SYS_POLL_H)
check_include_files(sys/timeb.h HAVE_SYS_TIMEB_H)
check_include_files(sys/types.h HAVE_SYS_TYPES_H)
check_include_files(endian.h HAVE_ENDIAN_H)
check_include_files(sys/filio.h HAVE_SYS_FILIO_H)
check_include_files(dirent.h HAVE_DIRENT_H)
check_include_files(unistd.h HAVE_UNISTD_H)
check_include_files(sys/resource.h HAVE_SYS_RESOURCE_H)
check_include_files(mach/clock.h HAVE_MACH_CLOCK_H)
check_include_files(mach-o/dyld.h HAVE_MACH_O_DYLD_H)
check_include_files(linux/version.h HAVE_LINUX_VERSION_H)

# for some reason, normal library searches always fail on broken windows
if (WIN32 AND NOT UNIX AND NOT MINGW AND NOT MSYS)
	set(HAVE_GETADDRINFO True)
	set(HAVE_INET_NTOP True)
endif()

configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)

# common build options can be passed to cmake using WITH_CFLAGS, WITH_LIBS,
# and WITH_INCLUDES.
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/inc ${WITH_INCLUDES})
add_definitions(${UCOMMON_FLAGS} ${WITH_CFLAGS})
link_libraries(${WITH_LIBS})

# by default we build static libs for windows, shared libs for unix.  
# we may also set this from a top level cmake or -DWITH_XX_LIBS
if(UNIX)
	set(BUILD_LIBRARY_TYPE SHARED)
else()
	set(BUILD_LIBRARY_TYPE STATIC)
endif()

if(WITH_SHARED_LIBS)
	set(BUILD_LIBRARY_TYPE SHARED)
endif()

if(WITH_STATIC_LIBS)
	set(BUILD_LIBRARY_TYPE STATIC)
endif()

file(GLOB ucommon_src src/*.cpp)
add_library(ucommon ${BUILD_LIBRARY_TYPE} ${ucommon_src})
set_target_properties(ucommon PROPERTIES VERSION ${VERSION} SOVERSION ${SOVERSION})
target_link_libraries(ucommon ${UCOMMON_LIBS} ${WITH_LIBS})
install(TARGETS ucommon DESTINATION lib)
