Commit f7a40a82b0f530e08e0d9619f1b4fe91a6f19793

Vicent Martí 2012-12-19T10:26:01

Merge pull request #1162 from scunz/cmake_cleanups RFC: Some cleanups/features in CMakeLists.txt

diff --git a/CMakeLists.txt b/CMakeLists.txt
index fc53077..696d6a0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,6 +14,67 @@
 PROJECT(libgit2 C)
 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
 
+# Build options
+#
+OPTION( BUILD_SHARED_LIBS	"Build Shared Library (OFF for Static)"	ON  )
+OPTION( THREADSAFE			"Build libgit2 as threadsafe"			OFF )
+OPTION( BUILD_CLAR			"Build Tests using the Clar suite"		ON  )
+OPTION( BUILD_EXAMPLES		"Build library usage example apps"		OFF )
+OPTION( TAGS				"Generate tags"							OFF )
+OPTION( PROFILE				"Generate profiling information"		OFF )
+IF(MSVC)
+	# This option is only availalbe when building with MSVC. By default, libgit2 is
+	# build using the stdcall calling convention, as that's what the CLR expects by
+	# default and how the Windows API is built.
+	#
+	# If you are writing a C or C++ program and want to link to libgit2, you have to
+	# either:
+	# - Add /Gz to the compiler options of _your_ program / library.
+	# - Turn this option off by invoking CMake with the "-DSTDCALL=Off" argument.
+	#
+	OPTION( STDCALL			"Build libgit2 with the __stdcall convention"	ON  )
+ENDIF()
+
+# Installation paths
+#
+SET(BIN_INSTALL_DIR bin CACHE PATH "Where to install binaries to.")
+SET(LIB_INSTALL_DIR lib CACHE PATH "Where to install libraries to.")
+SET(INCLUDE_INSTALL_DIR include CACHE PATH "Where to install headers to.")
+
+FUNCTION(TARGET_OS_LIBRARIES target)
+	IF(WIN32)
+		TARGET_LINK_LIBRARIES(${target} ws2_32)
+	ELSEIF(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
+		TARGET_LINK_LIBRARIES(${target} socket nsl)
+	ENDIF ()
+	IF(THREADSAFE)
+		TARGET_LINK_LIBRARIES(${target} ${CMAKE_THREAD_LIBS_INIT})
+	ENDIF()
+ENDFUNCTION()
+
+# For the MSVC IDE, this function splits up the source files like windows explorer does.
+# This is esp. useful with the libgit2_clar project, were usually 2 or more files share
+# the same name.
+# Sadly, this file grouping is a per-directory option in cmake and not per-target, resulting
+# in empty virtual folders "tests-clar" for the git2.dll
+FUNCTION(MSVC_SPLIT_SOURCES target)
+	IF(MSVC_IDE)
+		GET_TARGET_PROPERTY(sources ${target} SOURCES)
+		FOREACH(source ${sources})
+			IF(source MATCHES ".*/")
+				STRING(REPLACE ${CMAKE_CURRENT_SOURCE_DIR}/ "" rel ${source})
+				IF(rel)
+					STRING(REGEX REPLACE "/([^/]*)$" "" rel ${rel})
+					IF(rel)
+						STRING(REPLACE "/" "\\\\" rel ${rel})
+						SOURCE_GROUP(${rel} FILES ${source})
+					ENDIF()
+				ENDIF()
+			ENDIF()
+		ENDFOREACH()
+	ENDIF()
+ENDFUNCTION()
+
 FILE(STRINGS "include/git2/version.h" GIT2_HEADER REGEX "^#define LIBGIT2_VERSION \"[^\"]*\"$")
 
 STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"([0-9]+).*$" "\\1" LIBGIT2_VERSION_MAJOR "${GIT2_HEADER}")
@@ -27,13 +88,14 @@ IF (AMIGA)
 ENDIF()
 
 # Find required dependencies
-INCLUDE_DIRECTORIES(src include deps/http-parser)
+INCLUDE_DIRECTORIES(src include)
 
 IF (WIN32 AND NOT MINGW)
 	ADD_DEFINITIONS(-DGIT_WINHTTP)
 ELSE ()
 	FIND_PACKAGE(OpenSSL)
 	FILE(GLOB SRC_HTTP deps/http-parser/*.c)
+	INCLUDE_DIRECTORIES(deps/http-parser)
 ENDIF()
 
 # Specify sha1 implementation
@@ -49,44 +111,29 @@ ELSE()
 	FILE(GLOB SRC_SHA1 src/hash/hash_generic.c)
 ENDIF()
 
-IF (NOT WIN32)
-	FIND_PACKAGE(ZLIB)
-	IF (CMAKE_SYSTEM_NAME STREQUAL "AmigaOS")
-		INCLUDE_DIRECTORIES(deps/regex)
-		SET(SRC_REGEX deps/regex/regex.c)
-	ENDIF()
-ELSE()
-	# Windows doesn't understand POSIX regex on its own
+# Include POSIX regex when it is required
+IF(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "AmigaOS")
 	INCLUDE_DIRECTORIES(deps/regex)
 	SET(SRC_REGEX deps/regex/regex.c)
 ENDIF()
 
+# Optional external dependency: zlib
+IF(NOT ZLIB_LIBRARY)
+	# It's optional, but FIND_PACKAGE gives a warning that looks more like an error.
+	FIND_PACKAGE(ZLIB QUIET)
+ENDIF()
 IF (ZLIB_FOUND)
 	INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS})
 	LINK_LIBRARIES(${ZLIB_LIBRARIES})
-ELSE (ZLIB_FOUND)
+ELSE()
+	MESSAGE( "zlib was not found; using bundled 3rd-party sources." )
 	INCLUDE_DIRECTORIES(deps/zlib)
 	ADD_DEFINITIONS(-DNO_VIZ -DSTDC -DNO_GZIP)
 	FILE(GLOB SRC_ZLIB deps/zlib/*.c)
 ENDIF()
 
-# Installation paths
-SET(BIN_INSTALL_DIR bin CACHE PATH "Where to install binaries to.")
-SET(LIB_INSTALL_DIR lib CACHE PATH "Where to install libraries to.")
-SET(INCLUDE_INSTALL_DIR include CACHE PATH "Where to install headers to.")
-
-# Build options
-OPTION (BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" ON)
-OPTION (THREADSAFE "Build libgit2 as threadsafe" OFF)
-OPTION (BUILD_CLAR "Build Tests using the Clar suite" ON)
-OPTION (BUILD_EXAMPLES "Build library usage example apps" OFF)
-OPTION (TAGS "Generate tags" OFF)
-OPTION (PROFILE "Generate profiling information" OFF)
-
 # Platform specific compilation flags
 IF (MSVC)
-	# Default to stdcall, as that's what the CLR expects and how the Windows API is built
-	OPTION (STDCALL "Buildl libgit2 with the __stdcall convention" ON)
 
     STRING(REPLACE "/Zm1000" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
 
@@ -148,26 +195,22 @@ FILE(GLOB SRC_H include/git2/*.h)
 # On Windows use specific platform sources
 IF (WIN32 AND NOT CYGWIN)
 	ADD_DEFINITIONS(-DWIN32 -D_DEBUG -D_WIN32_WINNT=0x0501)
-	FILE(GLOB SRC src/*.c src/transports/*.c src/xdiff/*.c src/win32/*.c src/compat/*.c)
-ELSEIF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
-	FILE(GLOB SRC src/*.c src/transports/*.c src/xdiff/*.c src/unix/*.c src/compat/*.c)
+	FILE(GLOB SRC_OS src/win32/*.c)
 ELSEIF (AMIGA)
 	ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R)
-	FILE(GLOB SRC src/*.c src/transports/*.c src/xdiff/*.c src/amiga/*.c src/compat/*.c)
+	FILE(GLOB SRC_OS src/amiga/*.c)
 ELSE()
-	FILE(GLOB SRC src/*.c src/transports/*.c src/xdiff/*.c src/unix/*.c)
-ENDIF ()
+	FILE(GLOB SRC_OS src/unix/*.c)
+ENDIF()
+FILE(GLOB SRC_GIT2 src/*.c src/transports/*.c src/xdiff/*.c)
 
 # Compile and link libgit2
-ADD_LIBRARY(git2 ${SRC} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1} ${WIN_RC})
+ADD_LIBRARY(git2 ${SRC_GIT2} ${SRC_OS} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1} ${WIN_RC})
+TARGET_LINK_LIBRARIES(git2 ${SSL_LIBRARIES})
+TARGET_OS_LIBRARIES(git2)
 
-IF (WIN32)
-	TARGET_LINK_LIBRARIES(git2 ws2_32)
-ELSEIF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
-	TARGET_LINK_LIBRARIES(git2 socket nsl)
-ENDIF ()
+MSVC_SPLIT_SOURCES(git2)
 
-TARGET_LINK_LIBRARIES(git2 ${CMAKE_THREAD_LIBS_INIT} ${SSL_LIBRARIES})
 SET_TARGET_PROPERTIES(git2 PROPERTIES VERSION ${LIBGIT2_VERSION_STRING})
 SET_TARGET_PROPERTIES(git2 PROPERTIES SOVERSION ${LIBGIT2_VERSION_MAJOR})
 CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libgit2.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libgit2.pc @ONLY)
@@ -208,20 +251,16 @@ IF (BUILD_CLAR)
 		DEPENDS ${CLAR_PATH}/clar ${SRC_TEST}
 		WORKING_DIRECTORY ${CLAR_PATH}
 	)
-	ADD_EXECUTABLE(libgit2_clar ${SRC} ${CLAR_PATH}/clar_main.c ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1})
-	TARGET_LINK_LIBRARIES(libgit2_clar ${CMAKE_THREAD_LIBS_INIT} ${SSL_LIBRARIES})
+	ADD_EXECUTABLE(libgit2_clar ${SRC_GIT2} ${SRC_OS} ${CLAR_PATH}/clar_main.c ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1})
+	TARGET_LINK_LIBRARIES(libgit2_clar ${SSL_LIBRARIES})
+	TARGET_OS_LIBRARIES(libgit2_clar)
+	MSVC_SPLIT_SOURCES(libgit2_clar)
 
         IF (MSVC_IDE)
            # Precompiled headers
            SET_TARGET_PROPERTIES(libgit2_clar PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
         ENDIF ()
 
-	IF (WIN32)
-		TARGET_LINK_LIBRARIES(libgit2_clar ws2_32)
-	ELSEIF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
-		TARGET_LINK_LIBRARIES(libgit2_clar socket nsl)
-	ENDIF ()
-
 	ENABLE_TESTING()
 	ADD_TEST(libgit2_clar libgit2_clar -iall)
 ENDIF ()