Commit d80d9d56a7f3150ed205baff6b09c3090dd785af

Etienne Samson 2019-08-17T12:17:21

cmake: streamline *.pc file handling via a module

diff --git a/cmake/Modules/PkgBuildConfig.cmake b/cmake/Modules/PkgBuildConfig.cmake
new file mode 100644
index 0000000..1c0079e
--- /dev/null
+++ b/cmake/Modules/PkgBuildConfig.cmake
@@ -0,0 +1,110 @@
+# pkg-config file generation
+#
+# Uses the following globals:
+# - PKG_BUILD_PREFIX: the build location (aka prefix). Defaults to CMAKE_INSTALL_PREFIX
+# - PKG_BUILD_LIBDIR: the libdir location. Defaults to ${prefix}/lib.
+# - PKG_BUILD_INCLUDEDIR: the includedir location. Defaults to ${prefix}/include.
+#
+
+function(pkg_build_config)
+    set(options)
+    set(oneValueArgs NAME DESCRIPTION VERSION FILENAME LIBS_SELF)
+    set(multiValueArgs LIBS PRIVATE_LIBS REQUIRES CFLAGS)
+
+    cmake_parse_arguments(PKGCONFIG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+    if (NOT DEFINED PKGCONFIG_FILENAME AND DEFINED PKGCONFIG_NAME)
+        set(PKGCONFIG_FILENAME ${PKGCONFIG_NAME})
+    endif()
+    if (NOT DEFINED PKGCONFIG_FILENAME)
+        message(FATAL_ERROR "Missing FILENAME argument")
+    endif()
+    set(PKGCONFIG_FILE "${PROJECT_BINARY_DIR}/${PKGCONFIG_FILENAME}.pc")
+
+    if (NOT DEFINED PKGCONFIG_DESCRIPTION)
+        message(FATAL_ERROR "Missing DESCRIPTION argument")
+    endif()
+
+    if (NOT DEFINED PKGCONFIG_VERSION)
+        message(FATAL_ERROR "Missing VERSION argument")
+    endif()
+
+    if (DEFINED PKG_BUILD_PREFIX)
+        set(PKGCONFIG_PREFIX "${PKG_BUILD_PREFIX}")
+    else()
+        set(PKGCONFIG_PREFIX "${CMAKE_INSTALL_PREFIX}")
+    endif()
+
+    if(DEFINED PKG_BUILD_LIBDIR)
+        if (IS_ABSOLUTE ${PKG_BUILD_LIBDIR})
+            set(PKGCONFIG_LIBDIR ${PKG_BUILD_LIBDIR})
+        else()
+            set(PKGCONFIG_LIBDIR "\${prefix}/${PKG_BUILD_LIBDIR}")
+        endif()
+    else()
+        set(PKGCONFIG_LIBDIR "\${prefix}/lib")
+    endif()
+
+    if(DEFINED PKG_BUILD_INCLUDEDIR)
+        if (IS_ABSOLUTE ${PKG_BUILD_INCLUDEDIR})
+            set(PKGCONFIG_INCLUDEDIR ${PKG_BUILD_INCLUDEDIR})
+        else()
+            set(PKGCONFIG_INCLUDEDIR "\${prefix}/${PKG_BUILD_INCLUDEDIR}")
+        endif()
+    else()
+        set(PKGCONFIG_INCLUDEDIR "\${prefix}/include")
+    endif()
+
+    # Write .pc "header"
+    file(WRITE "${PKGCONFIG_FILE}"
+        "prefix=\"${PKGCONFIG_PREFIX}\"\n"
+        "libdir=\"${PKGCONFIG_LIBDIR}\"\n"
+        "includedir=\"${PKGCONFIG_INCLUDEDIR}\"\n"
+        "\n"
+        "Name: ${PKGCONFIG_NAME}\n"
+        "Description: ${PKGCONFIG_DESCRIPTION}\n"
+        "Version: ${PKGCONFIG_VERSION}\n"
+    )
+
+    # Prepare Libs
+    if(NOT DEFINED PKGCONFIG_LIBS_SELF)
+        set(PKGCONFIG_LIBS_SELF "${PKGCONFIG_FILE}")
+    endif()
+
+    if(NOT DEFINED PKGCONFIG_LIBS)
+        set(PKGCONFIG_LIBS "-l${PKGCONFIG_LIBS_SELF}")
+    else()
+        list(INSERT PKGCONFIG_LIBS 0 "-l${PKGCONFIG_LIBS_SELF}")
+    endif()
+
+    list(REMOVE_DUPLICATES PKGCONFIG_LIBS)
+    string(REPLACE ";" " " PKGCONFIG_LIBS "${PKGCONFIG_LIBS}")
+    file(APPEND "${PKGCONFIG_FILE}" "Libs: -L\${libdir} ${PKGCONFIG_LIBS}\n")
+
+    # Prepare Libs.private
+    if(DEFINED PKGCONFIG_PRIVATE_LIBS)
+        list(REMOVE_DUPLICATES PKGCONFIG_PRIVATE_LIBS)
+        string(REPLACE ";" " " PKGCONFIG_PRIVATE_LIBS "${PKGCONFIG_PRIVATE_LIBS}")
+        file(APPEND "${PKGCONFIG_FILE}" "Libs.private: ${PKGCONFIG_PRIVATE_LIBS}\n")
+    endif()
+
+    # Prepare Requires.private
+    if(DEFINED PKGCONFIG_REQUIRES)
+        list(REMOVE_DUPLICATES PKGCONFIG_REQUIRES)
+        string(REPLACE ";" " " PKGCONFIG_REQUIRES "${PKGCONFIG_REQUIRES}")
+        file(APPEND "${PKGCONFIG_FILE}" "Requires.private: ${PKGCONFIG_REQUIRES}\n")
+    endif()
+
+    # Prepare Cflags
+    if(DEFINED PKGCONFIG_CFLAGS)
+        string(REPLACE ";" " " PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS}")
+    else()
+        set(PKGCONFIG_CFLAGS "")
+    endif()
+    file(APPEND "${PKGCONFIG_FILE}" "Cflags: -I\${includedir} ${PKGCONFIG_CFLAGS}\n")
+
+    # Install .pc file
+    install(FILES "${PKGCONFIG_FILE}"
+        DESTINATION "${PKGCONFIG_PREFIX}/${PKGCONFIG_LIBDIR}/pkgconfig"
+    )
+endfunction()
diff --git a/libgit2.pc.in b/libgit2.pc.in
deleted file mode 100644
index 96b9659..0000000
--- a/libgit2.pc.in
+++ /dev/null
@@ -1,13 +0,0 @@
-prefix="@PKGCONFIG_PREFIX@"
-libdir=@PKGCONFIG_LIBDIR@
-includedir=@PKGCONFIG_INCLUDEDIR@
-
-Name: libgit2
-Description: The git library, take 2
-Version: @LIBGIT2_VERSION_STRING@
-
-Libs: -L${libdir} -lgit2
-Libs.private: @LIBGIT2_PC_LIBS@
-Requires.private: @LIBGIT2_PC_REQUIRES@
-
-Cflags: -I${includedir}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index de7e408..f086b92 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -3,6 +3,8 @@ IF(DEBUG_POOL)
 ENDIF()
 ADD_FEATURE_INFO(debugpool GIT_DEBUG_POOL "debug pool allocator")
 
+INCLUDE(PkgBuildConfig)
+
 # This variable will contain the libraries we need to put into
 # libgit2.pc's Requires.private. That is, what we're linking to or
 # what someone who's statically linking us needs to link to.
@@ -25,23 +27,6 @@ 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.")
 
-# Set a couple variables to be substituted inside the .pc file.
-# We can't just use LIB_INSTALL_DIR in the .pc file, as passing them as absolue
-# or relative paths is both valid and supported by cmake.
-SET (PKGCONFIG_PREFIX ${CMAKE_INSTALL_PREFIX})
-
-IF(IS_ABSOLUTE ${LIB_INSTALL_DIR})
-  SET (PKGCONFIG_LIBDIR ${LIB_INSTALL_DIR})
-ELSE(IS_ABSOLUTE ${LIB_INSTALL_DIR})
-  SET (PKGCONFIG_LIBDIR "\${prefix}/${LIB_INSTALL_DIR}")
-ENDIF (IS_ABSOLUTE ${LIB_INSTALL_DIR})
-
-IF(IS_ABSOLUTE ${INCLUDE_INSTALL_DIR})
-  SET (PKGCONFIG_INCLUDEDIR ${INCLUDE_INSTALL_DIR})
-ELSE(IS_ABSOLUTE ${INCLUDE_INSTALL_DIR})
-  SET (PKGCONFIG_INCLUDEDIR "\${prefix}/${INCLUDE_INSTALL_DIR}")
-ENDIF(IS_ABSOLUTE ${INCLUDE_INSTALL_DIR})
-
 # Enable tracing
 IF (ENABLE_TRACE STREQUAL "ON")
 	SET(GIT_TRACE 1)
@@ -397,10 +382,13 @@ IF (SONAME)
 	ENDIF()
 ENDIF()
 
-LIST(REMOVE_DUPLICATES LIBGIT2_PC_REQUIRES)
-STRING(REPLACE ";" " " LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES}")
-STRING(REPLACE ";" " " LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS}")
-CONFIGURE_FILE(${libgit2_SOURCE_DIR}/libgit2.pc.in ${libgit2_BINARY_DIR}/libgit2.pc @ONLY)
+PKG_BUILD_CONFIG(NAME libgit2
+	VERSION ${LIBGIT2_VERSION_STRING}
+	DESCRIPTION "The git library, take 2"
+	LIBS_SELF git2
+	PRIVATE_LIBS ${LIBGIT2_PC_LIBS}
+	REQUIRES ${LIBGIT2_PC_REQUIRES}
+)
 
 IF (MSVC_IDE)
    # Precompiled headers
@@ -414,6 +402,5 @@ INSTALL(TARGETS git2
 	LIBRARY DESTINATION ${LIB_INSTALL_DIR}
 	ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
 )
-INSTALL(FILES ${libgit2_BINARY_DIR}/libgit2.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig )
 INSTALL(DIRECTORY ${libgit2_SOURCE_DIR}/include/git2 DESTINATION ${INCLUDE_INSTALL_DIR} )
 INSTALL(FILES ${libgit2_SOURCE_DIR}/include/git2.h DESTINATION ${INCLUDE_INSTALL_DIR} )