From 3e5ef9e181084cc88ef59811e6eba1d7d82ba4cf Mon Sep 17 00:00:00 2001
From: Szczepan Zalega <szczepan@nitrokey.com>
Date: Sun, 22 Oct 2017 09:02:41 +0200
Subject: Use hand-inserted version. Remove one Git pass.

Full version name should consist of official version and Git one
Git describe should never fail with --always switch
Add more build specific information
Save compilation definitions and flags
Move getting information to the end of CMakeLists.txt
Use configuration over definitions
Proper implementation in C API for getting version
Test case for getting version.
Working configure file

Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
---
 CMakeLists.txt           | 56 +++++++++++++++++++++++++++---------------------
 NK_C_API.cc              |  9 +++++++-
 unittest/test_C_API.cpp  |  2 +-
 unittest/test_offline.cc |  9 ++++++++
 version.cc.in            |  4 ++++
 version.h                | 12 +++++++++++
 6 files changed, 65 insertions(+), 27 deletions(-)
 create mode 100644 version.cc.in
 create mode 100644 version.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 537a54a..f82df8e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,43 +28,19 @@ IF (UNIX)
 ENDIF()
 
 project(libnitrokey)
-SET(PROJECT_VERSION "3.1")
 set(CMAKE_CXX_STANDARD 14)
 
 set(LIBNK_VERSION_MAJOR 3) #  reminder: incompatible API changes
 set(LIBNK_VERSION_MINOR 1) #  add functionality in a backwards-compatible manner
 set(LIBNK_VERSION_PATCH 0) #  make backwards-compatible bug fixes
 set(LIBNK_VERSION ${LIBNK_VERSION_MAJOR}.${LIBNK_VERSION_MINOR}.${LIBNK_VERSION_PATCH} )
+SET(PROJECT_VERSION "${LIBNK_VERSION}")
 
 
 include(GNUInstallDirs)
 
 OPTION(LIBNITROKEY_STATIC "Build libnitrokey statically" FALSE)
 
-# Getter for the library version
-#
-# If a git tag is available, we use it.
-# Else, we use a git version and we raise a warning.
-#
-exec_program(
-  "git"
-  ${CMAKE_CURRENT_SOURCE_DIR}
-  ARGS "describe"
-  OUTPUT_VARIABLE GIT_VERSION)
-
-IF(${GIT_TAG} MATCHES "fatal:.*")
-MESSAGE(WARNING "Unable to find a git tag. Using git version instead.")
-exec_program(
-  "git"
-  ${CMAKE_CURRENT_SOURCE_DIR}
-  ARGS "rev-parse HEAD"
-  OUTPUT_VARIABLE GIT_VERSION)
-ENDIF()
-
-MESSAGE("LIBRARY VERSION: ${GIT_VERSION} ")
-ADD_DEFINITIONS(-DVERSION="${GIT_VERSION}")
-
-
 IF (NOT CMAKE_BUILD_TYPE)
     IF(APPLE)
         # Issues occur when build with enabled optimizations
@@ -98,6 +74,8 @@ set(SOURCE_FILES
     device.cc
     log.cc
     misc.cc
+    version.cc
+    version.h
     NitrokeyManager.cc
     NK_C_API.h
     NK_C_API.cc
@@ -196,6 +174,34 @@ IF (COMPILE_TESTS)
 ENDIF()
 
 
+# Getter for the library version
+exec_program(
+        "git"
+        ${CMAKE_CURRENT_SOURCE_DIR}
+        ARGS "describe --always --dirty=-modified"
+        OUTPUT_VARIABLE GIT_VERSION)
+
+get_target_property(COMPILE_DEFINITIONS ${LIBNAME} COMPILE_DEFINITIONS)
+get_target_property(COMPILE_FLAGS ${LIBNAME} COMPILE_FLAGS)
+SET(FULL_VERSION "${PROJECT_VERSION}/${GIT_VERSION}")
+SET(VERSION_MORE "${CMAKE_BUILD_TYPE}/${COMPILE_FLAGS}")
+IF(COMPILE_DEFINITIONS)
+	SET(VERSION_MORE "${VERSION_MORE}/${COMPILE_DEFINITIONS}")
+ENDIF()
+IF(ADD_TSAN)
+	SET(VERSION_MORE "${VERSION_MORE} TSAN")
+ENDIF()
+IF(ADD_ASAN)
+	SET(VERSION_MORE "${VERSION_MORE} ASAN")
+ENDIF()
+IF(LIBNITROKEY_STATIC)
+	SET(VERSION_MORE "${VERSION_MORE} STATIC")
+ENDIF()
+MESSAGE("${PROJECT_NAME}: Version set: ${FULL_VERSION}")
+MESSAGE("${PROJECT_NAME}: Version additional: ${VERSION_MORE}")
+
+configure_file(version.cc.in ${CMAKE_SOURCE_DIR}/version.cc)
+
 
 #SET(CPACK_GENERATOR
 #        "DEB;RPM")
diff --git a/NK_C_API.cc b/NK_C_API.cc
index 6f4c757..704feec 100644
--- a/NK_C_API.cc
+++ b/NK_C_API.cc
@@ -4,6 +4,7 @@
 #include <cstring>
 #include "include/LibraryException.h"
 #include "include/cxx_semantics.h"
+#include "version.h"
 
 #ifdef _MSC_VER
 #ifdef _WIN32
@@ -99,6 +100,7 @@ uint8_t get_without_result(T func){
 }
 
 
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -533,7 +535,12 @@ extern "C" {
 
 
 	NK_C_API const char * NK_version() {
-	   return VERSION;
+	  auto m = NitrokeyManager::instance();
+	  return get_with_string_result([&](){
+	    const std::string & s = Version::version;
+	    char * rs = strndup(s.c_str(), max_string_field_length);
+	    return rs;
+	  });
 	}
 
 #ifdef __cplusplus
diff --git a/unittest/test_C_API.cpp b/unittest/test_C_API.cpp
index 160145b..a351139 100644
--- a/unittest/test_C_API.cpp
+++ b/unittest/test_C_API.cpp
@@ -31,4 +31,4 @@ TEST_CASE("Check long strings", "[STANDARD]") {
   result = NK_change_user_PIN(pin, longPin);
   REQUIRE(result == TOO_LONG_STRING);
   CAPTURE(result);
-}
\ No newline at end of file
+}
diff --git a/unittest/test_offline.cc b/unittest/test_offline.cc
index 58c7555..f4063ab 100644
--- a/unittest/test_offline.cc
+++ b/unittest/test_offline.cc
@@ -11,6 +11,15 @@ using namespace nitrokey;
 
 //This test suite assumes no Pro or Storage devices are connected
 
+#include <string.h>
+TEST_CASE("Get version", "[BASIC]") {
+  const char * v = NK_version();
+  CAPTURE(v);
+  REQUIRE( strnlen(v, 200) > 0 );
+  free((void*)v);
+}
+
+
 TEST_CASE("Return false on no device connected", "[fast]") {
   INFO("This test case assumes no Pro or Storage devices are connected");
   auto stick = make_shared<Stick20>();
diff --git a/version.cc.in b/version.cc.in
new file mode 100644
index 0000000..3de030c
--- /dev/null
+++ b/version.cc.in
@@ -0,0 +1,4 @@
+#include "version.h"
+
+const std::string Version::version = "${FULL_VERSION}";
+const std::string Version::version_more = "${VERSION_MORE}";
\ No newline at end of file
diff --git a/version.h b/version.h
new file mode 100644
index 0000000..011d7ac
--- /dev/null
+++ b/version.h
@@ -0,0 +1,12 @@
+#ifndef NITROKEYAPP_VERSION_H
+#define NITROKEYAPP_VERSION_H
+
+#include <string>
+
+namespace Version {
+  extern const std::string version;
+  extern const std::string version_more;
+};
+
+
+#endif //NITROKEYAPP_VERSION_H
-- 
cgit v1.2.3