Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add soversion to shared library #23

Merged
merged 3 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ project(
LANGUAGES CXX
)

# See notes in GNUmakefile about using abi-compliance-checker.
# soversion is major ABI version.
set( abi_version 1.0.0 )
string( REPLACE "." ";" abi_list "${abi_version}" )
list( GET abi_list 0 soversion )

include( CheckCXXCompilerFlag )

# When built as a sub-project, add a namespace to make targets unique,
Expand All @@ -32,6 +38,16 @@ endif()

#-------------------------------------------------------------------------------
# Options
if (testsweeper_is_project)
set( log "" CACHE STRING "Shorthand for CMAKE_MESSAGE_LOG_LEVEL" )
set_property( CACHE log PROPERTY STRINGS
FATAL_ERROR SEND_ERROR WARNING AUTHOR_WARNING DEPRECATION
NOTICE STATUS VERBOSE DEBUG TRACE )
if (log)
set( CMAKE_MESSAGE_LOG_LEVEL "${log}" )
endif()
endif()

option( BUILD_SHARED_LIBS "Build shared libraries" true )
option( build_tests "Build test suite" "${testsweeper_is_project}" )
option( color "Use ANSI color output" true )
Expand Down Expand Up @@ -68,6 +84,8 @@ use_openmp = ${use_openmp}
testsweeper_install = ${testsweeper_install}
testsweeper_is_project = ${testsweeper_is_project}
testsweeper_ = ${testsweeper_}
abi_version = ${abi_version}
soversion = ${soversion}
" )

#-------------------------------------------------------------------------------
Expand Down Expand Up @@ -130,6 +148,8 @@ set_target_properties(
CXX_STANDARD_REQUIRED true # prohibit < c++17
CXX_EXTENSIONS false # prohibit gnu++17
WINDOWS_EXPORT_ALL_SYMBOLS ON
VERSION "${abi_version}"
SOVERSION "${soversion}"
)

if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.15)
Expand Down
66 changes: 51 additions & 15 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,32 +44,53 @@ ifeq ($(origin LD),default)
LD = $(CXX)
endif

# Use abi-compliance-checker to compare the ABI (application binary
# interface) of 2 releases. Changing the ABI does not necessarily change
# the API (application programming interface). Rearranging a struct or
# changing a by-value argument from int64 to int doesn't change the
# API--no source code changes are required, just a recompile.
#
# if structs or routines are changed or removed:
# bump major version and reset minor, revision = 0;
# else if structs or routines are added:
# bump minor version and reset revision = 0;
# else (e.g., bug fixes):
# bump revision
#
# soversion is major ABI version.
abi_version = 1.0.0
soversion = ${word 1, ${subst ., ,${abi_version}}}

#-------------------------------------------------------------------------------
# auto-detect OS
# $OSTYPE may not be exported from the shell, so echo it
ostype := $(shell echo $${OSTYPE})
ifneq ($(findstring darwin, $(ostype)),)
# MacOS is darwin
macos = 1
# MacOS needs shared library's path set, and shared library version.
ldflags_shared = -install_name @rpath/${notdir $@} \
-current_version ${abi_version} \
-compatibility_version ${soversion}
so = dylib
so2 = .dylib
# on macOS, .dylib comes after version: libfoo.4.dylib
else
so = so
so1 = .so
# on Linux, .so comes before version: libfoo.so.4
endif

#-------------------------------------------------------------------------------
# if shared
ifneq ($(static),1)
CXXFLAGS += -fPIC
LDFLAGS += -fPIC
lib_ext = so
lib_ext = ${so}
else
lib_ext = a
endif

#-------------------------------------------------------------------------------
# MacOS needs shared library's path set
ifeq ($(macos),1)
install_name = -install_name @rpath/$(notdir $@)
else
install_name =
endif

#-------------------------------------------------------------------------------
# Files

Expand Down Expand Up @@ -124,7 +145,7 @@ install: lib
mkdir -p $(DESTDIR)$(prefix)/include
mkdir -p $(DESTDIR)$(prefix)/lib$(LIB_SUFFIX)
cp $(headers) $(DESTDIR)$(prefix)/include
cp $(lib) $(DESTDIR)$(prefix)/lib$(LIB_SUFFIX)
cp -av libtestsweeper.* $(DESTDIR)$(prefix)/lib$(LIB_SUFFIX)

uninstall:
$(RM) $(addprefix $(DESTDIR)$(prefix)/include/, $(headers))
Expand All @@ -136,12 +157,21 @@ $(lib_obj) $(tester_obj): make.inc

#-------------------------------------------------------------------------------
# TestSweeper library
lib_a = libtestsweeper.a
lib_so = libtestsweeper.so
lib = libtestsweeper.$(lib_ext)
lib_name = libtestsweeper
lib_a = ${lib_name}.a
lib_so = ${lib_name}.${so}
lib = ${lib_name}.${lib_ext}

# libfoo.so.3 or libfoo.3.dylib
lib_so_abi_version = ${lib_name}${so1}.${abi_version}${so2}
lib_so_soversion = ${lib_name}${so1}.${soversion}${so2}

${lib_so_abi_version}: ${lib_obj}
${LD} ${LDFLAGS} -shared ${ldflags_shared} ${lib_obj} ${LIBS} -o $@

$(lib_so): $(lib_obj)
$(LD) $(LDFLAGS) -shared $(install_name) $(lib_obj) $(LIBS) -o $@
${lib_so}: | ${lib_so_abi_version}
ln -fs ${lib_so_abi_version} ${lib_so}
ln -fs ${lib_so_abi_version} ${lib_so_soversion}

$(lib_a): $(lib_obj)
$(RM) $@
Expand Down Expand Up @@ -217,10 +247,15 @@ echo:
@echo "static = '$(static)'"
@echo "id = '$(id)'"
@echo "last_id = '$(last_id)'"
@echo "abi_version = '${abi_version}'"
@echo "soversion = '${soversion}'"
@echo
@echo "lib_name = ${lib_name}"
@echo "lib_a = $(lib_a)"
@echo "lib_so = $(lib_so)"
@echo "lib = $(lib)"
@echo "lib_so_abi_version = ${lib_so_abi_version}"
@echo "lib_so_soversion = ${lib_so_soversion}"
@echo
@echo "lib_src = $(lib_src)"
@echo
Expand All @@ -240,6 +275,7 @@ echo:
@echo "LD = $(LD)"
@echo "LDFLAGS = $(LDFLAGS)"
@echo "LIBS = $(LIBS)"
@echo "ldflags_shared = ${ldflags_shared}"
@echo
@echo "TEST_LDFLAGS = $(TEST_LDFLAGS)"
@echo "TEST_LIBS = $(TEST_LIBS)"
50 changes: 50 additions & 0 deletions GNUmakefile.subdir
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copyright (c) 2017-2023, University of Tennessee. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
# This program is free software: you can redistribute it and/or modify it under
# the terms of the BSD 3-Clause license. See the accompanying LICENSE file.
#
# Subdirectories include this makefile to forward rules to the top level makefile.
# Define ${top} for where the top level is.
# Example: src/GNUmakefile:
# top = ..
# include ${top}/GNUmakefile.subdir

.SUFFIXES:

pwd := ${shell pwd}
abs_top := ${abspath ${top}}
cdir := ${subst ${abs_top}/,,${pwd}}

.DEFAULT_GOAL: ${cdir}
.PHONY: ${cdir}

${cdir}:
cd ${top} && ${MAKE} $@

DONT_FORWARD += echo_sub
echo_sub:
@echo "pwd ${pwd}"
@echo "abs_top ${abs_top}"
@echo "cdir ${cdir}"

# ------------------------------------------------------------------------------
ifneq (${MAKECMDGOALS},)

# If arguments are given, presumably files like test.o, forward them to top
# with cdir prefix.
# All files are forwarded as one rule, based on first; rest are quietly ignored.
goals := ${filter-out echo ${DONT_FORWARD}, ${MAKECMDGOALS}}
forward := ${addprefix ${cdir}/, ${goals}}
first := ${firstword ${goals}}
rest := ${wordlist 2, ${words ${goals}}, ${goals}}

${first}: force
cd ${top} && ${MAKE} ${forward}

${rest}: force
@echo > /dev/null

endif
# ------------------------------------------------------------------------------

force: ;
2 changes: 2 additions & 0 deletions test/GNUmakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
top = ..
include ${top}/GNUmakefile.subdir
7 changes: 0 additions & 7 deletions testsweeper.hh
Original file line number Diff line number Diff line change
Expand Up @@ -421,13 +421,6 @@ public:
values_[ index_ ] = value;
}

[[deprecated( "use param() instead of param.value(). To be removed 2024-03." )]]
T& value()
{
used_ = true;
return values_[ index_ ];
}

void set_default( const T& default_value )
{
default_value_ = default_value;
Expand Down
Loading