### CMake project for building libusb from source
cmake_minimum_required(VERSION 3.10)
project(libusb
	VERSION 1.0
	LANGUAGES C
)

## Configure libusb for the machine
if(UNIX)
	message("[${PROJECT_NAME}] Configure libusb..")

	execute_process(
		COMMAND chmod +x bootstrap.sh
		COMMAND sh autogen.sh --disable-static
		WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
		RESULT_VARIABLE autogen_res
	)

	if (NOT ${autogen_res} STREQUAL "0")
		message(FATAL_ERROR "Fatal error while configuring libusb: ${autogen_res}")
	endif()

	execute_process(
		COMMAND chmod -x bootstrap.sh
		WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
	)
endif(UNIX)

# Debug messages
# message("[${PROJECT_NAME}] MAIN PROJECT: ${CMAKE_PROJECT_NAME}")

############### Files & Targets ############################
# Files of project and target to build                     #
############################################################
# Cross platform source directory
set(xplatform_source_dir ${CMAKE_CURRENT_SOURCE_DIR}/libusb)
# message("[${PROJECT_NAME}] XPLATFORM SOURCE DIR: ${xplatform_source_dir}")

# Native source directory
set(native_source_dir ${CMAKE_CURRENT_SOURCE_DIR}/libusb/os)
# message("[${PROJECT_NAME}] NATIVE SOURCE DIR: ${native_source_dir}")

# Native config directory
if(WIN32)
	set(native_config_dir ${CMAKE_CURRENT_SOURCE_DIR}/msvc)
endif(WIN32)

if(APPLE)
	set(native_config_dir ${CMAKE_CURRENT_SOURCE_DIR}/Xcode)
endif(APPLE)

if(UNIX AND NOT APPLE)
	set(native_config_dir ${CMAKE_CURRENT_SOURCE_DIR})
endif(UNIX AND NOT APPLE)
# message("[${PROJECT_NAME}] NATIVE CONFIG DIR: ${native_config_dir}")

# Platform agnostic source files
message("[${PROJECT_NAME}] Indexing platform agnostic source files..")
set(src_files
	${xplatform_source_dir}/core.c
	${xplatform_source_dir}/descriptor.c
	${xplatform_source_dir}/hotplug.c
	${xplatform_source_dir}/io.c
	${xplatform_source_dir}/strerror.c
	${xplatform_source_dir}/sync.c
)

### Platform dependant source files ###
# Add Windows platform source files
if(WIN32)
	message("[${PROJECT_NAME}] Indexing Windows platform source files..")
	set(src_files
		${src_files}
		${native_source_dir}/threads_windows.c
		${native_source_dir}/windows_common.c
		${native_source_dir}/windows_usbdk.c
		${native_source_dir}/windows_winusb.c
		${native_source_dir}/events_windows.c
	)
endif(WIN32)

# Add Mac platform source files
if(APPLE)
	message("[${PROJECT_NAME}] Indexing Mac platform source files..")
	set(src_files
		${src_files}
		${native_source_dir}/darwin_usb.c
		${native_source_dir}/events_posix.c
		${native_source_dir}/threads_posix.c
	)
endif(APPLE)

# Add Linux platform source files
if(UNIX AND NOT APPLE)
	message("[${PROJECT_NAME}] Indexing Linux platform source files..")
	list(APPEND src_files
		${native_source_dir}/linux_netlink.c
		${native_source_dir}/linux_udev.c
		${native_source_dir}/linux_usbfs.c
		${native_source_dir}/events_posix.c
		${native_source_dir}/threads_posix.c
	)
endif(UNIX AND NOT APPLE)
source_group("Sources" FILES ${src_files})

# Platform agnostic header Files
message("[${PROJECT_NAME}] Indexing platform agnostic header files..")
set(hdr_files
	${xplatform_source_dir}/libusb.h
	${xplatform_source_dir}/libusbi.h
	${xplatform_source_dir}/version.h
	${xplatform_source_dir}/version_nano.h
)

### Platform dependant header files ###
# Add Windows platform header files
if(WIN32)
	message("[${PROJECT_NAME}] Indexing Windows platform header files..")
	set(hdr_files
		${hdr_files}
		${native_source_dir}/threads_windows.h
		${native_source_dir}/windows_common.h
		${native_source_dir}/windows_usbdk.h
		${native_source_dir}/windows_winusb.h
		${native_source_dir}/events_windows.h
	)
endif(WIN32)

# Add Mac platform header files
if(APPLE)
	message("[${PROJECT_NAME}] Indexing Mac platform header files..")
	set(hdr_files
		${hdr_files}
		${native_source_dir}/darwin_usb.h
		${native_source_dir}/events_posix.h
		${native_source_dir}/threads_posix.h
	)
endif(APPLE)

# Add Linux platform header files
if(UNIX AND NOT APPLE)
	message("[${PROJECT_NAME}] Indexing Linux platform header files..")
	list(APPEND hdr_files
		${native_source_dir}/linux_usbfs.h
		${native_source_dir}/events_posix.h
		${native_source_dir}/threads_posix.h
	)
endif(UNIX AND NOT APPLE)
source_group("Headers" FILES ${hdr_files})

### Platform dependant resource files ###
# Add Windows platform resource files
if(WIN32)
	message("[${PROJECT_NAME}] Indexing Windows platform resource files..")
	set(rc_files
		${xplatform_source_dir}/libusb-1.0.rc
	)
	source_group("Resources" FILES ${rc_files})
endif(WIN32)

# Add library target to build
set(usb "${PROJECT_NAME}-${PROJECT_VERSION}")
add_library(${usb} SHARED
	${src_files}
	${hdr_files}
	${rc_files}
)

## Treat char as signed char
target_compile_options(${usb}
	PUBLIC
		-fsigned-char
)

## Define compile and link options for Windows
if(MSVC)
	target_compile_definitions(${usb} PRIVATE -DUNICODE -D_UNICODE)
	target_link_options(${usb}
		PRIVATE
			/DEF:${xplatform_source_dir}/libusb-1.0.def
			/ASSEMBLYRESOURCE:${xplatform_source_dir}/libusb-1.0.rc
	)
endif(MSVC)


## Modify output name on Mac/Linux
if(APPLE)
	set_target_properties(${usb} PROPERTIES OUTPUT_NAME "usb-1.0.0")
endif(APPLE)

if(UNIX AND NOT APPLE)
	set_target_properties(${usb} PROPERTIES OUTPUT_NAME "usb-1.0")
endif(UNIX AND NOT APPLE)

## Define include directories
target_include_directories(${usb}
	PUBLIC
		${xplatform_source_dir}
	PRIVATE
		${native_source_dir}
		${native_config_dir}
)

## Link required libraries
if(APPLE)
	# Find required shared libraries on Mac
	find_library(CORE_FOUNDATION_LIBRARY CoreFoundation)
	message(STATUS "CORE_FOUNDATION_LIBRARY is ${CORE_FOUNDATION_LIBRARY}")
	find_library(IOKIT_LIBRARY IOKit)
	message(STATUS "IOKIT_LIBRARY is ${IOKIT_LIBRARY}")
	find_library(OBJC_LIBRARY objc)
	message(STATUS "OBJC_LIBRARY is ${OBJC_LIBRARY}")
	find_library(SECURITY_LIBRARY Security)
	message(STATUS "SECURITY_LIBRARY is ${SECURITY_LIBRARY}")

	set(dependencies
		${CORE_FOUNDATION_LIBRARY}
		${IOKIT_LIBRARY}
		${OBJC_LIBRARY}
		${SECURITY_LIBRARY}
	)

	target_link_libraries(${usb}
		PRIVATE
			${dependencies}
	)
endif(APPLE)

if(UNIX AND NOT APPLE)
	target_link_libraries(${usb}
		PRIVATE
			udev
	)
endif(UNIX AND NOT APPLE)


## Install libusb
if (NOT DEFINED libusb_install_path)
	set(libusb_install_path "libusb_installed")
endif()

install(TARGETS ${usb} DESTINATION ${libusb_install_path})