Skip to content

Commit fd0331c

Browse files
committed
saving.
1 parent 1c2ee63 commit fd0331c

3 files changed

Lines changed: 163 additions & 2 deletions

File tree

CMakeLists.txt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
99
Debug Release RelWithDebInfo MinSizeRel)
1010
endif()
1111

12-
project(clhash LANGUAGES C CXX)
12+
project(clhash
13+
VERSION 1.0.0
14+
DESCRIPTION "Fast 64-bit universal hashing via carry-less multiplication"
15+
HOMEPAGE_URL "https://github.com/simdhash/clhash"
16+
LANGUAGES C CXX)
1317

1418
option(CLHASH_ENABLE_BITMIX "Enable CLHASH_BITMIX compile definition" OFF)
1519
include(cmake/CPM.cmake)
@@ -25,6 +29,13 @@ set(CMAKE_CXX_EXTENSIONS OFF)
2529
add_library(clhash src/clhash.c)
2630
add_library(clhash::clhash ALIAS clhash)
2731

32+
# Version the library artifact. For a shared build this drives SONAME and the
33+
# symlink chain (libclhash.so -> libclhash.so.1 -> libclhash.so.1.0.0). It is
34+
# harmless for the static build that we default to today.
35+
set_target_properties(clhash PROPERTIES
36+
VERSION ${PROJECT_VERSION}
37+
SOVERSION ${PROJECT_VERSION_MAJOR})
38+
2839
# Generator expressions so the include path is correct in both the build
2940
# tree and after `cmake --install`.
3041
target_include_directories(clhash PUBLIC
@@ -73,7 +84,7 @@ if(CLHASH_INSTALL)
7384
"include(\"\${CMAKE_CURRENT_LIST_DIR}/clhashTargets.cmake\")\n")
7485
write_basic_package_version_file(
7586
"${CMAKE_CURRENT_BINARY_DIR}/clhashConfigVersion.cmake"
76-
VERSION 1.0.0
87+
VERSION ${PROJECT_VERSION}
7788
COMPATIBILITY SameMajorVersion)
7889

7990
install(FILES

include/clhash.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,20 @@
2020
#ifndef INCLUDE_CLHASH_H_
2121
#define INCLUDE_CLHASH_H_
2222

23+
/*
24+
* Library version. These macros are kept in lock-step with the project version
25+
* in CMakeLists.txt; consumers can do compile-time checks such as
26+
*
27+
* #if (CLHASH_VERSION_MAJOR < 1) || \
28+
* (CLHASH_VERSION_MAJOR == 1 && CLHASH_VERSION_MINOR < 1)
29+
* #error "clhash >= 1.1 required"
30+
* #endif
31+
*/
32+
#define CLHASH_VERSION_MAJOR 1
33+
#define CLHASH_VERSION_MINOR 0
34+
#define CLHASH_VERSION_PATCH 0
35+
#define CLHASH_VERSION_STRING "1.0.0"
36+
2337

2438
#include <stdlib.h>
2539
#include <stdint.h> // life is short, please use a C99-compliant compiler

scripts/release.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#!/usr/bin/env python3
2+
"""Bump the clhash project version.
3+
4+
Updates the project version in two places in lock-step:
5+
- CMakeLists.txt (project(clhash ... VERSION X.Y.Z ...))
6+
- include/clhash.h (CLHASH_VERSION_MAJOR / MINOR / PATCH / STRING)
7+
8+
It does NOT touch git; commit, tag, and push are left to the caller so you can
9+
review the diff first.
10+
11+
Usage:
12+
scripts/release.py 1.0.1 # bump to 1.0.1
13+
scripts/release.py --show # print the current version
14+
scripts/release.py --dry-run 1.0.1 # show what would change
15+
"""
16+
from __future__ import annotations
17+
18+
import argparse
19+
import re
20+
import sys
21+
from pathlib import Path
22+
23+
REPO = Path(__file__).resolve().parent.parent
24+
CMAKE = REPO / "CMakeLists.txt"
25+
HEADER = REPO / "include" / "clhash.h"
26+
27+
# X.Y.Z. We intentionally do NOT accept pre-release or build metadata here:
28+
# the release process is meant to produce clean, monotonic releases.
29+
VERSION_RE = re.compile(r"^\d+\.\d+\.\d+$")
30+
31+
32+
def parse_version(s: str) -> tuple[int, int, int]:
33+
if not VERSION_RE.match(s):
34+
sys.exit(f"error: version must be MAJOR.MINOR.PATCH, got {s!r}")
35+
a, b, c = s.split(".")
36+
return int(a), int(b), int(c)
37+
38+
39+
def read_current_version() -> str:
40+
text = CMAKE.read_text()
41+
m = re.search(
42+
r"project\s*\(\s*clhash\b[^)]*?\bVERSION\s+(\d+\.\d+\.\d+)",
43+
text, re.S,
44+
)
45+
if not m:
46+
sys.exit("error: could not find project(clhash ... VERSION X.Y.Z) in "
47+
f"{CMAKE.relative_to(REPO)}")
48+
return m.group(1)
49+
50+
51+
def bump_cmake(new: str) -> str:
52+
text = CMAKE.read_text()
53+
pattern = re.compile(
54+
r"(project\s*\(\s*clhash\b[^)]*?\bVERSION\s+)\d+\.\d+\.\d+",
55+
re.S,
56+
)
57+
new_text, n = pattern.subn(rf"\g<1>{new}", text, count=1)
58+
if n != 1:
59+
sys.exit(f"error: failed to rewrite project version in "
60+
f"{CMAKE.relative_to(REPO)}")
61+
return new_text
62+
63+
64+
def bump_header(new: str) -> str:
65+
text = HEADER.read_text()
66+
major, minor, patch = new.split(".")
67+
replacements = [
68+
(r"(#\s*define\s+CLHASH_VERSION_MAJOR\s+)\d+", rf"\g<1>{major}"),
69+
(r"(#\s*define\s+CLHASH_VERSION_MINOR\s+)\d+", rf"\g<1>{minor}"),
70+
(r"(#\s*define\s+CLHASH_VERSION_PATCH\s+)\d+", rf"\g<1>{patch}"),
71+
(r'(#\s*define\s+CLHASH_VERSION_STRING\s+)"[^"]*"', rf'\g<1>"{new}"'),
72+
]
73+
new_text = text
74+
for pat, repl in replacements:
75+
new_text, n = re.subn(pat, repl, new_text, count=1)
76+
if n != 1:
77+
sys.exit(f"error: failed to rewrite {pat!r} in "
78+
f"{HEADER.relative_to(REPO)}")
79+
return new_text
80+
81+
82+
def main() -> None:
83+
ap = argparse.ArgumentParser(
84+
description="Bump the clhash project version.",
85+
formatter_class=argparse.RawDescriptionHelpFormatter,
86+
epilog=__doc__.split("Usage:", 1)[1] if __doc__ and "Usage:" in __doc__ else None,
87+
)
88+
ap.add_argument("version", nargs="?",
89+
help="New version in MAJOR.MINOR.PATCH form (e.g. 1.0.1).")
90+
ap.add_argument("--show", action="store_true",
91+
help="Print the current version and exit.")
92+
ap.add_argument("--dry-run", action="store_true",
93+
help="Show the planned change without writing files.")
94+
args = ap.parse_args()
95+
96+
current = read_current_version()
97+
98+
if args.show:
99+
print(current)
100+
return
101+
102+
if not args.version:
103+
ap.error("missing version argument (or pass --show)")
104+
105+
new = args.version
106+
new_t = parse_version(new)
107+
cur_t = parse_version(current)
108+
if new_t == cur_t:
109+
sys.exit(f"error: new version {new} equals current version")
110+
if new_t < cur_t:
111+
sys.exit(f"error: new version {new} is older than current {current}")
112+
113+
cmake_new = bump_cmake(new)
114+
header_new = bump_header(new)
115+
116+
if args.dry_run:
117+
print(f"would bump {current} -> {new}")
118+
print(f" {CMAKE.relative_to(REPO)}")
119+
print(f" {HEADER.relative_to(REPO)}")
120+
return
121+
122+
CMAKE.write_text(cmake_new)
123+
HEADER.write_text(header_new)
124+
print(f"bumped {current} -> {new}")
125+
print(f" updated {CMAKE.relative_to(REPO)}")
126+
print(f" updated {HEADER.relative_to(REPO)}")
127+
print()
128+
print("Next steps:")
129+
print(f" git add CMakeLists.txt include/clhash.h")
130+
print(f" git commit -m 'Bump version to {new}'")
131+
print(f" git tag -a v{new} -m 'Release {new}'")
132+
print(f" git push origin HEAD && git push origin v{new}")
133+
134+
135+
if __name__ == "__main__":
136+
main()

0 commit comments

Comments
 (0)