Commit ae30009e3d1312bf2a3816d40ba3c73587304068

Patrick Steinhardt 2020-07-12T16:01:15

Merge pull request #5547 from pks-t/pks/cmake-modernization-pt2 CMake modernization pt2

diff --git a/CMakeLists.txt b/CMakeLists.txt
index fb5202f..e745351 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,7 +13,7 @@
 
 CMAKE_MINIMUM_REQUIRED(VERSION 3.5.1)
 
-project(libgit2 C)
+project(libgit2 VERSION "1.0.1" LANGUAGES C)
 
 # Add find modules to the path
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${libgit2_SOURCE_DIR}/cmake/")
@@ -93,16 +93,6 @@ IF(MSVC)
 	OPTION(MSVC_CRTDBG 		"Enable CRTDBG memory leak reporting"			OFF)
 ENDIF()
 
-FILE(STRINGS "${libgit2_SOURCE_DIR}/include/git2/version.h" GIT2_HEADER REGEX "^#define LIBGIT2_VERSION \"[^\"]*\"$")
-
-STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"([0-9]+).*$" "\\1" LIBGIT2_VERSION_MAJOR "${GIT2_HEADER}")
-STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_MINOR  "${GIT2_HEADER}")
-STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_REV "${GIT2_HEADER}")
-SET(LIBGIT2_VERSION_STRING "${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}.${LIBGIT2_VERSION_REV}")
-
-FILE(STRINGS "${libgit2_SOURCE_DIR}/include/git2/version.h" GIT2_HEADER_SOVERSION REGEX "^#define LIBGIT2_SOVERSION \"([0-9.]+)\"$")
-STRING(REGEX REPLACE "^.*LIBGIT2_SOVERSION \"([0-9.]+)\"$" "\\1" LIBGIT2_SOVERSION "${GIT2_HEADER_SOVERSION}")
-
 IF (DEPRECATE_HARD)
 	ADD_DEFINITIONS(-DGIT_DEPRECATE_HARD)
 ENDIF()
@@ -175,7 +165,7 @@ IF (MSVC)
 	# /NXCOMPAT - Data execution prevention (DEP)
 	# /LARGEADDRESSAWARE - >2GB user address space on x86
 	# /VERSION - Embed version information in PE header
-	SET(CMAKE_EXE_LINKER_FLAGS "/DYNAMICBASE /NXCOMPAT /LARGEADDRESSAWARE /VERSION:${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}")
+	SET(CMAKE_EXE_LINKER_FLAGS "/DYNAMICBASE /NXCOMPAT /LARGEADDRESSAWARE /VERSION:${libgit2_VERSION_MAJOR}.${libgit2_VERSION_MINOR}")
 
 	IF (NOT (MSVC_VERSION LESS 1900))
 		# /GUARD:CF - Enable Control Flow Guard
diff --git a/cmake/CheckPrototypeDefinition.c.in b/cmake/CheckPrototypeDefinition.c.in
deleted file mode 100644
index a97344a..0000000
--- a/cmake/CheckPrototypeDefinition.c.in
+++ /dev/null
@@ -1,29 +0,0 @@
-@CHECK_PROTOTYPE_DEFINITION_HEADER@
-
-static void cmakeRequireSymbol(int dummy, ...) {
-  (void) dummy;
-}
-
-static void checkSymbol(void) {
-#ifndef @CHECK_PROTOTYPE_DEFINITION_SYMBOL@
-  cmakeRequireSymbol(0, &@CHECK_PROTOTYPE_DEFINITION_SYMBOL@);
-#endif
-}
-
-@CHECK_PROTOTYPE_DEFINITION_PROTO@ {
-  return @CHECK_PROTOTYPE_DEFINITION_RETURN@;
-}
-
-#ifdef __CLASSIC_C__
-int main() {
-  int ac;
-  char*av[];
-#else
-int main(int ac, char *av[]) {
-#endif
-  checkSymbol();
-  if (ac > 1000) {
-    return *av[0];
-  }
-  return 0;
-}
diff --git a/cmake/CheckPrototypeDefinition.cmake b/cmake/CheckPrototypeDefinition.cmake
deleted file mode 100644
index 244b9b5..0000000
--- a/cmake/CheckPrototypeDefinition.cmake
+++ /dev/null
@@ -1,96 +0,0 @@
-# - Check if the protoype we expect is correct.
-# check_prototype_definition(FUNCTION PROTOTYPE RETURN HEADER VARIABLE)
-#  FUNCTION - The name of the function (used to check if prototype exists)
-#  PROTOTYPE- The prototype to check.
-#  RETURN - The return value of the function.
-#  HEADER - The header files required.
-#  VARIABLE - The variable to store the result.
-# Example:
-#  check_prototype_definition(getpwent_r
-#   "struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)"
-#   "NULL"
-#   "unistd.h;pwd.h"
-#   SOLARIS_GETPWENT_R)
-# The following variables may be set before calling this macro to
-# modify the way the check is run:
-#
-#  CMAKE_REQUIRED_FLAGS = string of compile command line flags
-#  CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
-#  CMAKE_REQUIRED_INCLUDES = list of include directories
-#  CMAKE_REQUIRED_LIBRARIES = list of libraries to link
-
-#=============================================================================
-# Copyright 2005-2009 Kitware, Inc.
-# Copyright 2010-2011 Andreas Schneider <asn@cryptomilk.org>
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-# (To distribute this file outside of CMake, substitute the full
-#  License text for the above reference.)
-#
-
-get_filename_component(__check_proto_def_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
-
-function(CHECK_PROTOTYPE_DEFINITION _FUNCTION _PROTOTYPE _RETURN _HEADER _VARIABLE)
-
-  if ("${_VARIABLE}" MATCHES "^${_VARIABLE}$")
-    set(CHECK_PROTOTYPE_DEFINITION_CONTENT "/* */\n")
-
-    set(CHECK_PROTOTYPE_DEFINITION_FLAGS ${CMAKE_REQUIRED_FLAGS})
-    if (CMAKE_REQUIRED_LIBRARIES)
-      set(CHECK_PROTOTYPE_DEFINITION_LIBS
-        "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
-    else(CMAKE_REQUIRED_LIBRARIES)
-      set(CHECK_PROTOTYPE_DEFINITION_LIBS)
-    endif(CMAKE_REQUIRED_LIBRARIES)
-    if (CMAKE_REQUIRED_INCLUDES)
-      set(CMAKE_SYMBOL_EXISTS_INCLUDES
-        "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
-    else(CMAKE_REQUIRED_INCLUDES)
-      set(CMAKE_SYMBOL_EXISTS_INCLUDES)
-    endif(CMAKE_REQUIRED_INCLUDES)
-
-    foreach(_FILE ${_HEADER})
-      set(CHECK_PROTOTYPE_DEFINITION_HEADER
-        "${CHECK_PROTOTYPE_DEFINITION_HEADER}#include <${_FILE}>\n")
-    endforeach(_FILE)
-
-    set(CHECK_PROTOTYPE_DEFINITION_SYMBOL ${_FUNCTION})
-    set(CHECK_PROTOTYPE_DEFINITION_PROTO ${_PROTOTYPE})
-    set(CHECK_PROTOTYPE_DEFINITION_RETURN ${_RETURN})
-
-    configure_file("${__check_proto_def_dir}/CheckPrototypeDefinition.c.in"
-      "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c" @ONLY)
-
-    file(READ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c _SOURCE)
-
-    try_compile(${_VARIABLE}
-      ${CMAKE_BINARY_DIR}
-      ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c
-      COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
-      CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${CHECK_PROTOTYPE_DEFINITION_FLAGS}
-      "${CHECK_PROTOTYPE_DEFINITION_LIBS}"
-      "${CMAKE_SYMBOL_EXISTS_INCLUDES}"
-      OUTPUT_VARIABLE OUTPUT)
-
-    if (${_VARIABLE})
-      set(${_VARIABLE} 1 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}")
-      message(STATUS "Checking prototype ${_FUNCTION} for ${_VARIABLE} - True")
-      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
-        "Determining if the prototype ${_FUNCTION} exists for ${_VARIABLE} passed with the following output:\n"
-        "${OUTPUT}\n\n")
-    else (${_VARIABLE})
-      message(STATUS "Checking prototype ${_FUNCTION} for ${_VARIABLE} - False")
-      set(${_VARIABLE} 0 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}")
-      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
-        "Determining if the prototype ${_FUNCTION} exists for ${_VARIABLE} failed with the following output:\n"
-        "${OUTPUT}\n\n${_SOURCE}\n\n")
-    endif (${_VARIABLE})
-  endif("${_VARIABLE}" MATCHES "^${_VARIABLE}$")
-
-endfunction(CHECK_PROTOTYPE_DEFINITION)
diff --git a/script/release.py b/script/release.py
index 99ff8ec..1a240de 100755
--- a/script/release.py
+++ b/script/release.py
@@ -40,6 +40,15 @@ def verify_version(version):
         'SOVERSION':    [ '"{}.{}"'.format(version.major, version.minor), None ],
     }
 
+    # Parse CMakeLists
+    with open('CMakeLists.txt') as f:
+        for line in f.readlines():
+            if line.startswith('project(libgit2 VERSION "{}"'.format(version)):
+                break
+        else:
+            raise Error("cmake: invalid project definition")
+
+    # Parse version.h
     with open('include/git2/version.h') as f:
         lines = f.readlines()
 
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8f139ec..d01cc64 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,3 +1,6 @@
+add_library(git2internal OBJECT)
+set_target_properties(git2internal PROPERTIES C_STANDARD 90)
+
 IF(DEBUG_POOL)
 	SET(GIT_DEBUG_POOL 1)
 ENDIF()
@@ -38,19 +41,19 @@ CHECK_PROTOTYPE_DEFINITION(qsort_r
 	"void qsort_r(void *base, size_t nmemb, size_t size, void *thunk, int (*compar)(void *, const void *, const void *))"
 	"" "stdlib.h" HAVE_QSORT_R_BSD)
 IF (HAVE_QSORT_R_BSD)
-	ADD_DEFINITIONS(-DHAVE_QSORT_R_BSD)
+	target_compile_definitions(git2internal PRIVATE HAVE_QSORT_R_BSD)
 ENDIF()
 
 CHECK_PROTOTYPE_DEFINITION(qsort_r
 	"void qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg)"
 	"" "stdlib.h" HAVE_QSORT_R_GNU)
 IF (HAVE_QSORT_R_GNU)
-	ADD_DEFINITIONS(-DHAVE_QSORT_R_GNU)
+	target_compile_definitions(git2internal PRIVATE HAVE_QSORT_R_GNU)
 ENDIF()
 
 CHECK_FUNCTION_EXISTS(qsort_s HAVE_QSORT_S)
 IF (HAVE_QSORT_S)
-	ADD_DEFINITIONS(-DHAVE_QSORT_S)
+	target_compile_definitions(git2internal PRIVATE HAVE_QSORT_S)
 ENDIF ()
 
 # Find required dependencies
@@ -81,6 +84,8 @@ ADD_FEATURE_INFO(threadsafe THREADSAFE "threadsafe support")
 if(WIN32 AND EMBED_SSH_PATH)
 	file(GLOB SRC_SSH "${EMBED_SSH_PATH}/src/*.c")
 	list(SORT SRC_SSH)
+	target_sources(git2internal PRIVATE ${SRC_SSH})
+
 	list(APPEND LIBGIT2_SYSTEM_INCLUDES "${EMBED_SSH_PATH}/include")
 	file(WRITE "${EMBED_SSH_PATH}/src/libssh2_config.h" "#define HAVE_WINCNG\n#define LIBSSH2_WINCNG\n#include \"../win32/libssh2_config.h\"")
 	set(GIT_SSH 1)
@@ -104,8 +109,9 @@ IF (WIN32 AND WINHTTP)
 	LIST(APPEND LIBGIT2_PC_LIBS "-lrpcrt4" "-lcrypt32" "-lole32")
 ENDIF()
 
-Include(SelectHTTPSBackend)
-Include(SelectHashes)
+include(SelectHTTPSBackend)
+include(SelectHashes)
+target_sources(git2internal PRIVATE ${SRC_SHA1})
 
 # Specify regular expression implementation
 FIND_PACKAGE(PCRE)
@@ -267,7 +273,7 @@ ELSEIF (HAVE_STRUCT_STAT_ST_MTIME_NSEC)
 	SET(GIT_USE_STAT_MTIME_NSEC 1)
 ENDIF()
 
-ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
+target_compile_definitions(git2internal PRIVATE _FILE_OFFSET_BITS=64)
 
 # Collect sourcefiles
 file(GLOB SRC_H
@@ -275,6 +281,7 @@ file(GLOB SRC_H
 	"${libgit2_SOURCE_DIR}/include/git2/*.h"
 	"${libgit2_SOURCE_DIR}/include/git2/sys/*.h")
 list(SORT SRC_H)
+target_sources(git2internal PRIVATE ${SRC_H})
 
 # On Windows use specific platform sources
 if(WIN32 AND NOT CYGWIN)
@@ -282,15 +289,17 @@ if(WIN32 AND NOT CYGWIN)
 
 	file(GLOB SRC_OS win32/*.c win32/*.h)
 	list(SORT SRC_OS)
+	target_sources(git2internal PRIVATE ${SRC_OS})
 elseif(AMIGA)
-	add_definitions(-DNO_ADDRINFO -DNO_READDIR_R -DNO_MMAP)
+	target_compile_definitions(git2internal PRIVATE NO_ADDRINFO NO_READDIR_R NO_MMAP)
 else()
 	file(GLOB SRC_OS unix/*.c unix/*.h)
 	list(SORT SRC_OS)
+	target_sources(git2internal PRIVATE ${SRC_OS})
 endif()
 
 IF (USE_LEAK_CHECKER STREQUAL "valgrind")
-	ADD_DEFINITIONS(-DVALGRIND)
+	target_compile_definitions(git2internal PRIVATE VALGRIND)
 ENDIF()
 
 file(GLOB SRC_GIT2 *.c *.h
@@ -299,6 +308,7 @@ file(GLOB SRC_GIT2 *.c *.h
 	transports/*.c transports/*.h
 	xdiff/*.c xdiff/*.h)
 list(SORT SRC_GIT2)
+target_sources(git2internal PRIVATE ${SRC_GIT2})
 
 IF(APPLE)
 	# The old Secure Transport API has been deprecated in macOS 10.15.
@@ -325,10 +335,6 @@ ENDIF()
 
 CONFIGURE_FILE(features.h.in git2/sys/features.h)
 
-SET(LIBGIT2_SOURCES ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_SSH} ${SRC_SHA1})
-
-ADD_LIBRARY(git2internal OBJECT ${LIBGIT2_SOURCES})
-SET_TARGET_PROPERTIES(git2internal PROPERTIES C_STANDARD 90)
 IDE_SPLIT_SOURCES(git2internal)
 LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:git2internal>)
 
@@ -364,19 +370,19 @@ ENDIF()
 
 IDE_SPLIT_SOURCES(git2)
 
-IF (SONAME)
-	SET_TARGET_PROPERTIES(git2 PROPERTIES VERSION ${LIBGIT2_VERSION_STRING})
-	SET_TARGET_PROPERTIES(git2 PROPERTIES SOVERSION ${LIBGIT2_SOVERSION})
-	IF (LIBGIT2_FILENAME)
-		ADD_DEFINITIONS(-DLIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\")
-		SET_TARGET_PROPERTIES(git2 PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME})
-	ELSEIF (DEFINED LIBGIT2_PREFIX)
-		SET_TARGET_PROPERTIES(git2 PROPERTIES PREFIX "${LIBGIT2_PREFIX}")
-	ENDIF()
-ENDIF()
+if(SONAME)
+	set_target_properties(git2 PROPERTIES VERSION ${libgit2_VERSION})
+	set_target_properties(git2 PROPERTIES SOVERSION "${libgit2_VERSION_MAJOR}.${libgit2_VERSION_MINOR}")
+	if(LIBGIT2_FILENAME)
+		target_compile_definitions(git2internal PRIVATE LIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\")
+		set_target_properties(git2 PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME})
+	elseif(DEFINED LIBGIT2_PREFIX)
+		set_target_properties(git2 PROPERTIES PREFIX "${LIBGIT2_PREFIX}")
+	endif()
+endif()
 
 PKG_BUILD_CONFIG(NAME libgit2
-	VERSION ${LIBGIT2_VERSION_STRING}
+	VERSION ${libgit2_VERSION}
 	DESCRIPTION "The git library, take 2"
 	LIBS_SELF git2
 	PRIVATE_LIBS ${LIBGIT2_PC_LIBS}