Skip to content

Commit bd1a80e

Browse files
hamishunesteffin
andauthored
Adding a version.{h,cpp}
- Simple compile time version to headers. - Generated by cmake - so one less place to update. - Also embedded version in the compiled library in case one needs sanity check. Co-authored-by: Enrico Steffinlongo <enrylongo@gmail.com>
1 parent 143cf32 commit bd1a80e

File tree

6 files changed

+233
-3
lines changed

6 files changed

+233
-3
lines changed

OLD_INSTALL.txt

+9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22
===> Refer to INSTALL.md for newer cmake-based installation. <===
33
===> We no longer recommend this method to install HElib. <===
44

5+
Additional Notes, September 2020
6+
--------------------------------
7+
version.in.h header and some source code (version.in.cpp and
8+
TestVersion.in.cpp) has been added so that HElib can introspect on its version.
9+
These are template files that cmake fills in the version numbers for us during
10+
a build. The old Makefile does not compile these. So, if you wish to use them
11+
we recommend moving to the cmake build.
12+
13+
514
HElib Installation Notes, August 2020
615
---------------------------------------
716
Much has changed since the note in 2015 and there are many updates. So this

include/helib/version.in.h

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* Copyright (C) 2020 IBM Corp.
2+
* This program is Licensed under the Apache License, Version 2.0
3+
* (the "License"); you may not use this file except in compliance
4+
* with the License. You may obtain a copy of the License at
5+
* http://www.apache.org/licenses/LICENSE-2.0
6+
* Unless required by applicable law or agreed to in writing, software
7+
* distributed under the License is distributed on an "AS IS" BASIS,
8+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
* See the License for the specific language governing permissions and
10+
* limitations under the License. See accompanying LICENSE file.
11+
*/
12+
13+
#ifndef HELIB_VERSION_H
14+
#define HELIB_VERSION_H
15+
16+
namespace helib {
17+
18+
/**
19+
* @class version
20+
* @brief The class acts as a namespace with all members static.
21+
* Holds the version number for this code of HElib.
22+
**/
23+
struct version
24+
{
25+
26+
// clang-format off
27+
/**
28+
* @brief The major number of this version of HElib.
29+
**/
30+
static constexpr long major = @PROJECT_VERSION_MAJOR@;
31+
/**
32+
* @brief The minor number of this version of HElib.
33+
**/
34+
static constexpr long minor = @PROJECT_VERSION_MINOR@;
35+
/**
36+
* @brief The patch number of this version of HElib.
37+
**/
38+
static constexpr long patch = @PROJECT_VERSION_PATCH@;
39+
// clang-format on
40+
41+
/**
42+
* @brief The string representation of this version of HElib.
43+
**/
44+
static constexpr auto asString = "v@PROJECT_VERSION@";
45+
46+
/**
47+
* @brief Function that returns whether this version of HElib is equal to or
48+
* higher than a specified version.
49+
* @param major The major version number.
50+
* @param minor The minor version number.
51+
* @param patch The patch version number.
52+
* @return `true` if current HElib version is greater than or equal to the
53+
* specified version version.
54+
**/
55+
static inline constexpr bool greaterEquals(long major_,
56+
long minor_ = 0,
57+
long patch_ = 0)
58+
{
59+
if (major_ < 0 || minor_ < 0 || patch_ < 0)
60+
return false;
61+
long min_version = (((major_ << 8) ^ minor_) << 8) ^ patch_;
62+
long our_version = (((major << 8) ^ minor) << 8) ^ patch;
63+
return our_version >= min_version;
64+
}
65+
66+
/**
67+
* @brief Get the string version from the HElib compiled library instead of
68+
* the one defined in the header.
69+
* @return A string representing the version of HElib stored in the compiled
70+
* library instead of from the one defined in the header.
71+
**/
72+
static const char* libString();
73+
74+
}; // struct version
75+
76+
} // namespace helib
77+
78+
#endif // HELIB_VERSION_H

src/CMakeLists.txt

+19-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ project(helib
2020
set(PROJECT_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/../include")
2121
# Location of the google tests
2222
set(PROJECT_TESTS_DIR "${PROJECT_SOURCE_DIR}/../tests")
23+
# Location of helib headers
24+
set(HELIB_HEADER_DIR "${PROJECT_INCLUDE_DIR}/helib")
2325

2426
# We assume enable threads is passed correctly (already checked)
2527
if (HELIB_REQUIRES_PTHREADS)
@@ -36,6 +38,14 @@ else ()
3638
"${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}")
3739
endif ()
3840

41+
# Generate version.{h,cpp}
42+
configure_file(${HELIB_HEADER_DIR}/version.in.h
43+
${CMAKE_CURRENT_BINARY_DIR}/helib/version.h
44+
@ONLY)
45+
configure_file(version.in.cpp
46+
${CMAKE_CURRENT_BINARY_DIR}/version.cpp
47+
@ONLY)
48+
3949
if (ENABLE_TEST)
4050
# Download and unpack googletest at configure time
4151
message(STATUS "Setting up googletest framework")
@@ -113,9 +123,10 @@ set(HELIB_SRCS
113123
"sample.cpp"
114124
"tableLookup.cpp"
115125
"timing.cpp"
116-
"zzX.cpp")
126+
"zzX.cpp"
127+
"${CMAKE_CURRENT_BINARY_DIR}/version.cpp" # version.cpp is auto-generated in CMAKE_CURRENT_BINARY_DIR
128+
)
117129

118-
set(HELIB_HEADER_DIR "${PROJECT_INCLUDE_DIR}/helib")
119130
set(HELIB_HEADERS
120131
"${HELIB_HEADER_DIR}/helib.h"
121132
"${HELIB_HEADER_DIR}/apiAttributes.h"
@@ -171,7 +182,9 @@ set(HELIB_HEADERS
171182
"${HELIB_HEADER_DIR}/exceptions.h"
172183
"${HELIB_HEADER_DIR}/PGFFT.h"
173184
"${HELIB_HEADER_DIR}/fhe_stats.h"
174-
"${HELIB_HEADER_DIR}/zeroValue.h")
185+
"${HELIB_HEADER_DIR}/zeroValue.h"
186+
"${CMAKE_CURRENT_BINARY_DIR}/helib/version.h" # version.h is auto-generated in CMAKE_CURRENT_BINARY_DIR
187+
)
175188

176189
set(LEGACY_TEST_SRCS
177190
"Test_approxNums.cpp"
@@ -262,6 +275,9 @@ target_include_directories(
262275
# looking for HElib in /usr/local/include
263276
# Headers used from source/build location:
264277
"$<BUILD_INTERFACE:${PROJECT_INCLUDE_DIR}>"
278+
# Adding CMAKE_CURRENT_BINARY_DIR to include files to access the
279+
# auto-generated version.h file.
280+
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>"
265281
# Headers used from the installed location:
266282
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
267283

src/version.in.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <helib/version.h>
2+
3+
namespace helib {
4+
5+
// This is stored in the compiled library.
6+
static constexpr char versionInLib[] = "v@PROJECT_VERSION@";
7+
8+
const char* version::libString() { return versionInLib; }
9+
10+
} // namespace helib

tests/CMakeLists.txt

+10
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212

1313
# Gtests configuration file
1414

15+
# TestVersion will be generated in CMAKE_CURRENT_BINARY_DIR.
16+
configure_file(TestVersion.in.cpp
17+
${CMAKE_CURRENT_BINARY_DIR}/TestVersion.cpp
18+
@ONLY)
19+
1520
set(GTEST_SRC
1621
"test_common.cpp"
1722
"TestArgMap.cpp"
@@ -27,6 +32,7 @@ set(GTEST_SRC
2732
"TestPolyModRing.cpp"
2833
"TestPtxt.cpp"
2934
"TestSet.cpp"
35+
"${CMAKE_CURRENT_BINARY_DIR}/TestVersion.cpp" # TestVersion.cpp is auto-generated in CMAKE_CURRENT_BINARY_DIR
3036
)
3137

3238
set(PORTED_LEGACY_TEST_SRC
@@ -100,13 +106,17 @@ set(TEST_NAMES
100106
"TestPtxt"
101107
"TestSet"
102108
"TestThinBootstrappingWithMultiplications"
109+
"TestVersion"
103110
)
104111

105112
# NOTE: Adding all PRIVATE_HELIB_CXX_FLAGS to the tests will add -fPIC too.
106113
# At the moment this does not affect compilation of the tests and does not
107114
# change their running time.
108115
target_compile_options(runTests PRIVATE ${PRIVATE_HELIB_CXX_FLAGS})
109116

117+
# Adding CMAKE_CURRENT_SOURCE_DIR to include files to access test_common.h.
118+
target_include_directories(runTests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
119+
110120
foreach (TEST_NAME ${TEST_NAMES})
111121
add_test(NAME "${TEST_NAME}" COMMAND runTests --gtest_filter=*${TEST_NAME}*)
112122
endforeach (TEST_NAME)

tests/TestVersion.in.cpp

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/* Copyright (C) 2020 IBM Corp.
2+
* This program is Licensed under the Apache License, Version 2.0
3+
* (the "License"); you may not use this file except in compliance
4+
* with the License. You may obtain a copy of the License at
5+
* http://www.apache.org/licenses/LICENSE-2.0
6+
* Unless required by applicable law or agreed to in writing, software
7+
* distributed under the License is distributed on an "AS IS" BASIS,
8+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
* See the License for the specific language governing permissions and
10+
* limitations under the License. See accompanying LICENSE file.
11+
*/
12+
13+
#include <helib/version.h>
14+
#include <tuple>
15+
#include <string>
16+
#include <regex>
17+
#include <sstream>
18+
#include <fstream>
19+
#include "test_common.h"
20+
#include "gtest/gtest.h"
21+
22+
namespace {
23+
24+
// Util function to grab version from cmake file.
25+
std::tuple<int, int, int, std::string> readVersionFromCmakeFile()
26+
{
27+
// File will be in src/, we are in tests/
28+
const std::string cmakeFilePath = "@CMAKE_SOURCE_DIR@/src/CMakeLists.txt";
29+
30+
// Slurp the file. It isn't a large file.
31+
std::string fileStr;
32+
33+
{
34+
std::ifstream cmakeFile(cmakeFilePath);
35+
if (!cmakeFile.is_open())
36+
throw std::runtime_error("Could not find '" + cmakeFilePath + "'.");
37+
38+
std::ostringstream oss;
39+
oss << cmakeFile.rdbuf();
40+
fileStr = oss.str();
41+
}
42+
43+
// Find the version.
44+
// e.g.
45+
// project(helib
46+
// VERSION x.y.z
47+
// LANGUAGES CXX)
48+
49+
std::regex re_version(
50+
R"(project[\s\S]*?helib[\s\S]*?VERSION[\s\S]*?((\d+)\.(\d+)\.(\d)))");
51+
std::smatch match;
52+
std::regex_search(fileStr, match, re_version);
53+
if (match.size() < 5) {
54+
std::ostringstream oss;
55+
oss << "Expected 5 matches, got " << match.size() << ".";
56+
throw std::runtime_error(oss.str());
57+
}
58+
59+
return std::tuple<int, int, int, std::string>(std::stoi(match[2]),
60+
std::stoi(match[3]),
61+
std::stoi(match[4]),
62+
"v" + match[1].str());
63+
}
64+
65+
TEST(TestVersion, versionMatchesThatFoundInCMakelists)
66+
{
67+
int major;
68+
int minor;
69+
int patch;
70+
std::string verStr;
71+
72+
std::tie(major, minor, patch, verStr) = readVersionFromCmakeFile();
73+
74+
// EXPECT_EQ does not like these class static members.
75+
int cur_maj = helib::version::major;
76+
int cur_min = helib::version::minor;
77+
int cur_pat = helib::version::patch;
78+
79+
EXPECT_EQ(cur_maj, major);
80+
EXPECT_EQ(cur_min, minor);
81+
EXPECT_EQ(cur_pat, patch);
82+
EXPECT_STREQ(helib::version::asString, verStr.c_str());
83+
}
84+
85+
TEST(TestVersion, versionGreaterThanOrEqualTo)
86+
{
87+
EXPECT_FALSE(helib::version::greaterEquals(3));
88+
EXPECT_FALSE(helib::version::greaterEquals(3, 1));
89+
EXPECT_FALSE(helib::version::greaterEquals(3, 1, 4));
90+
// Shouldn't work for negative numbers
91+
EXPECT_FALSE(helib::version::greaterEquals(1, -1, 0));
92+
EXPECT_FALSE(helib::version::greaterEquals(0, -1, 0));
93+
// Older version
94+
EXPECT_TRUE(helib::version::greaterEquals(1, 0, 0));
95+
// Current version
96+
// clang-format off
97+
EXPECT_TRUE(helib::version::greaterEquals(@PROJECT_VERSION_MAJOR@, @PROJECT_VERSION_MINOR@, @PROJECT_VERSION_PATCH@));
98+
// clang-format on
99+
}
100+
101+
TEST(TestVersion, versionLibString)
102+
{
103+
const char* libString = helib::version::libString();
104+
EXPECT_STREQ(libString, "v@PROJECT_VERSION@");
105+
}
106+
107+
} // namespace

0 commit comments

Comments
 (0)