From 19eb1e4bb740d72ebaddc9eb5084d8e013c68ddc Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 5 Jun 2020 10:07:33 +0200 Subject: cmake: specify project version We currently do not set up a project version within CMake, meaning that it can't be use by other projects including libgit2 as a sub-project and also not by other tools like IDEs. This commit changes this to always set up a project version, but instead of extracting it from the "version.h" header we now set it up directly. This is mostly to avoid mis-use of the previous `LIBGIT2_VERSION` variables, as we should now always use the `libgit2_VERSION` ones that are set up by CMake if one provides the "VERSION" keyword to the `project()` call. While this is one more moving target we need to adjust on releases, this commit also adjusts our release script to verify that the project version was incremented as expected. --- CMakeLists.txt | 14 ++------------ script/release.py | 9 +++++++++ src/CMakeLists.txt | 22 +++++++++++----------- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fb5202fd1..e745351b4 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/script/release.py b/script/release.py index 99ff8ecaf..1a240deca 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 8f139ec20..bbbfd0e5e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -364,19 +364,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) + 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() 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} -- cgit v1.2.1 From 53911edd46ea0946c4d6a53f9fd8c8d36a2b5104 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 5 Jun 2020 10:24:30 +0200 Subject: cmake: use git2internal target to populate sources Modern CMake is usually target-driven in that a target is first defined and then the likes of `target_sources`, `target_include_directories` etc. are used to further populate the target. We still use old-style CMake, where we first set up a set of variables and then populate the target in a single call. Let's migrate to modern CMake usage by starting to populate the sources of our git2internal target piece-by-piece. While this is a small step, it allows us to convert to target-based build instructions piece-by-piece. --- src/CMakeLists.txt | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bbbfd0e5e..4ec2091f1 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() @@ -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) @@ -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,11 +289,13 @@ 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) 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") @@ -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 $) -- cgit v1.2.1 From 4218403e99fd2407dfc7a6f36b3b02bc7073c709 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 5 Jun 2020 10:49:09 +0200 Subject: cmake: use target-specific compile definitions We set up some compile definitions as part of our src/CMakeLists.txt. While the definitions are global, we really only need them as part of the git2internal target which compiles all the objects. Let's thus use `target_compile_definitions` instead of `add_definitions`. --- src/CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4ec2091f1..d01cc6458 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -41,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 @@ -273,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 @@ -291,7 +291,7 @@ if(WIN32 AND NOT CYGWIN) 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) @@ -299,7 +299,7 @@ else() endif() IF (USE_LEAK_CHECKER STREQUAL "valgrind") - ADD_DEFINITIONS(-DVALGRIND) + target_compile_definitions(git2internal PRIVATE VALGRIND) ENDIF() file(GLOB SRC_GIT2 *.c *.h @@ -374,7 +374,7 @@ 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) - add_definitions(-DLIBGIT2_FILENAME=\"${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}") -- cgit v1.2.1 From 9bc6e655e1d10a0fa388e19fe72ee588cd4e2f96 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 5 Jun 2020 11:37:30 +0200 Subject: cmake: remove CheckPrototypeDefinition module In the past, we've imported the CheckPrototypeDefinition into our own module directory as it wasn't yet available in all supported CMake versions. Now that we require at least CMake v3.5, we don't need to bundle it anymore as it's included with the distribution already. Let's drop the included modules and always use upstream's version. --- cmake/CheckPrototypeDefinition.c.in | 29 ----------- cmake/CheckPrototypeDefinition.cmake | 96 ------------------------------------ 2 files changed, 125 deletions(-) delete mode 100644 cmake/CheckPrototypeDefinition.c.in delete mode 100644 cmake/CheckPrototypeDefinition.cmake diff --git a/cmake/CheckPrototypeDefinition.c.in b/cmake/CheckPrototypeDefinition.c.in deleted file mode 100644 index a97344ac3..000000000 --- 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 244b9b53b..000000000 --- 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 -# -# 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) -- cgit v1.2.1