Skip to content
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
50 changes: 25 additions & 25 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
cmake_minimum_required(VERSION 3.28)

project(msft_proxy4 VERSION 4.1.0 LANGUAGES CXX)
add_library(msft_proxy4 INTERFACE)
set_target_properties(msft_proxy4 PROPERTIES EXPORT_NAME proxy)
add_library(msft_proxy4::proxy ALIAS msft_proxy4)
project(msft_proxy5 VERSION 5.0.0 LANGUAGES CXX)
add_library(msft_proxy5 INTERFACE)
set_target_properties(msft_proxy5 PROPERTIES EXPORT_NAME proxy)
add_library(msft_proxy5::proxy ALIAS msft_proxy5)

# Do not enable building tests if proxy is consumed as
# subdirectory (e.g. by CMake FetchContent_Declare).
Expand Down Expand Up @@ -39,74 +39,74 @@ endif()
file(GLOB_RECURSE proxy_public_headers CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/include/proxy/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/include/proxy/*.ixx")
target_sources(msft_proxy4
target_sources(msft_proxy5
INTERFACE
FILE_SET public_headers
TYPE HEADERS
BASE_DIRS include
FILES ${proxy_public_headers}
)

target_compile_features(msft_proxy4 INTERFACE cxx_std_20)
target_compile_features(msft_proxy5 INTERFACE cxx_std_20)
target_include_directories(
msft_proxy4
msft_proxy5
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)

# Do not set the module target if proxy is consumed as a subdirectory.
if(PROJECT_IS_TOP_LEVEL)
set(msft_proxy4_INCLUDE_DIR include)
set(msft_proxy5_INCLUDE_DIR include)
if(PROXY_BUILD_MODULES)
include(cmake/msft_proxy4ModuleTargets.cmake)
include(cmake/msft_proxy5ModuleTargets.cmake)
endif()
else()
# Propagate the variable to the parent project
set(msft_proxy4_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
set(msft_proxy5_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
endif()

# install and export the project. project name - proxy

include(GNUInstallDirs)

install(
TARGETS msft_proxy4
EXPORT msft_proxy4Targets
TARGETS msft_proxy5
EXPORT msft_proxy5Targets
FILE_SET public_headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

install(
EXPORT msft_proxy4Targets
NAMESPACE msft_proxy4::
DESTINATION ${CMAKE_INSTALL_DATADIR}/msft_proxy4
EXPORT msft_proxy5Targets
NAMESPACE msft_proxy5::
DESTINATION ${CMAKE_INSTALL_DATADIR}/msft_proxy5
)
export(
TARGETS msft_proxy4
NAMESPACE msft_proxy4::
FILE msft_proxy4Targets.cmake
TARGETS msft_proxy5
NAMESPACE msft_proxy5::
FILE msft_proxy5Targets.cmake
)

include(CMakePackageConfigHelpers)
configure_package_config_file(
cmake/msft_proxy4Config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/cmake/msft_proxy4Config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_DATADIR}/msft_proxy4
cmake/msft_proxy5Config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/cmake/msft_proxy5Config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_DATADIR}/msft_proxy5
PATH_VARS CMAKE_INSTALL_INCLUDEDIR
)

include(CMakePackageConfigHelpers)
write_basic_package_version_file(
cmake/msft_proxy4ConfigVersion.cmake
cmake/msft_proxy5ConfigVersion.cmake
COMPATIBILITY SameMajorVersion
ARCH_INDEPENDENT
)

install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/cmake/msft_proxy4Config.cmake
${CMAKE_CURRENT_BINARY_DIR}/cmake/msft_proxy4ConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_DATADIR}/msft_proxy4
${CMAKE_CURRENT_BINARY_DIR}/cmake/msft_proxy5Config.cmake
${CMAKE_CURRENT_BINARY_DIR}/cmake/msft_proxy5ConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_DATADIR}/msft_proxy5
)

# build tests if BUILD_TESTING is ON
Expand Down
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module(
name = "proxy",
version = "4.1.0",
version = "5.0.0",
)

bazel_dep(name = "platforms", version = "1.1.0")
Expand Down
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,12 @@ Fetch via [CPM](https://github.com/cpm-cmake/CPM.cmake) (a thin wrapper over CMa

```cmake
CPMAddPackage(
NAME msft_proxy4
GIT_TAG 4.1.0
NAME msft_proxy5
GIT_TAG 5.0.0
GIT_REPOSITORY https://github.com/ngcpp/proxy.git
)

target_link_libraries(main PRIVATE msft_proxy4::proxy)
target_link_libraries(main PRIVATE msft_proxy5::proxy)
```

Or, if you already have a local clone, use `add_subdirectory(path/to/proxy)` instead of `CPMAddPackage`.
Expand All @@ -259,17 +259,17 @@ Place a wrap file at `subprojects/proxy.wrap` and Meson will fetch the source au
```ini
[wrap-git]
url = https://github.com/ngcpp/proxy.git
revision = 4.1.0
revision = 5.0.0

[provide]
dependency_names = msft_proxy4
dependency_names = msft_proxy5
```

Then in your `meson.build`:

```meson
msft_proxy4_dep = dependency('msft_proxy4')
executable('main', 'main.cpp', dependencies: msft_proxy4_dep)
msft_proxy5_dep = dependency('msft_proxy5')
executable('main', 'main.cpp', dependencies: msft_proxy5_dep)
```

### Bazel
Expand All @@ -279,7 +279,7 @@ The library is not yet published to the [Bazel Central Registry](https://registr
With **Bzlmod** (Bazel 7+), add to your `MODULE.bazel`:

```python
bazel_dep(name = "proxy", version = "4.1.0")
bazel_dep(name = "proxy", version = "5.0.0")
git_override(
module_name = "proxy",
remote = "https://github.com/ngcpp/proxy.git",
Expand All @@ -294,7 +294,7 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
name = "proxy",
remote = "https://github.com/ngcpp/proxy.git",
tag = "4.1.0",
tag = "5.0.0",
)
load("@proxy//:proxy_deps.bzl", "proxy_deps")
proxy_deps()
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ add_executable(
target_include_directories(msft_proxy_benchmarks PRIVATE .)
target_link_libraries(
msft_proxy_benchmarks
PRIVATE msft_proxy4::proxy benchmark::benchmark benchmark::benchmark_main
PRIVATE msft_proxy5::proxy benchmark::benchmark benchmark::benchmark_main
)
target_compile_options(
msft_proxy_benchmarks
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ benchmark(
'proxy_operation_benchmark_context.cpp',
),
implicit_include_directories: false,
dependencies: [msft_proxy4_dep, benchmark_dep],
dependencies: [msft_proxy5_dep, benchmark_dep],
cpp_args: cxx.get_argument_syntax() == 'msvc' ? ['/bigobj'] : [],
),
)
5 changes: 0 additions & 5 deletions cmake/msft_proxy4Config.cmake.in

This file was deleted.

34 changes: 0 additions & 34 deletions cmake/msft_proxy4ModuleTargets.cmake

This file was deleted.

5 changes: 5 additions & 0 deletions cmake/msft_proxy5Config.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@PACKAGE_INIT@

include("${CMAKE_CURRENT_LIST_DIR}/msft_proxy5Targets.cmake")
Comment thread
mingxwa marked this conversation as resolved.

set(msft_proxy5_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
34 changes: 34 additions & 0 deletions cmake/msft_proxy5ModuleTargets.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
if(NOT DEFINED msft_proxy5_INCLUDE_DIR)
message(
FATAL_ERROR
"`msft_proxy5_INCLUDE_DIR` must be defined to use this script."
)
endif()

message(
STATUS
"Declaring `msft_proxy5::proxy_module` target for include path `${msft_proxy5_INCLUDE_DIR}`"
)

add_library(msft_proxy5_module)
set_target_properties(
msft_proxy5_module
PROPERTIES SYSTEM TRUE EXCLUDE_FROM_ALL TRUE
)

add_library(msft_proxy5::proxy_module ALIAS msft_proxy5_module)
target_sources(
msft_proxy5_module
PUBLIC
FILE_SET CXX_MODULES
BASE_DIRS ${msft_proxy5_INCLUDE_DIR}
FILES ${msft_proxy5_INCLUDE_DIR}/proxy/v5/proxy.ixx
)
target_compile_features(msft_proxy5_module PUBLIC cxx_std_20)
target_compile_options(
msft_proxy5_module
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/utf-8>
$<$<CXX_COMPILER_ID:Clang,AppleClang>:-Wno-c++2b-extensions>
)
target_link_libraries(msft_proxy5_module PUBLIC msft_proxy5::proxy)
2 changes: 1 addition & 1 deletion docs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ foreach(i RANGE 0 ${_last})
add_executable(example_${_suffix} "${_cpp}")
target_link_libraries(
example_${_suffix}
PRIVATE msft_proxy4::proxy ${_dep_names}
PRIVATE msft_proxy5::proxy ${_dep_names}
)
target_compile_options(example_${_suffix} PRIVATE ${PROXY_BUILD_FLAGS})
add_test(NAME example_${_suffix} COMMAND example_${_suffix})
Expand Down
8 changes: 4 additions & 4 deletions docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,15 @@ Upgrading a small component is usually straightforward, but migrating a monorepo
1. **Minor or patch upgrades (e.g. 3.3.0 → 3.4.0)**
All 3.x.y releases preserve API/ABI compatibility, so different parts of the program may safely depend on different 3.x.y versions. No special action is required.

2. **Major upgrades (e.g. 3.4.0 → 4.0.0)**
2. **Major upgrades (e.g. 4.1.0 → 5.0.0)**
- If your current version is *earlier* than 3.4.0, migrate to 3.4.0 first.
- Starting with 3.4.0, each major release is placed in a versioned inline namespace (`pro::v3`, `pro::v4`, …).  When a translation unit sees multiple majors, qualify the namespace explicitly:
- Starting with 3.4.0, each major release is placed in a versioned inline namespace (`pro::v3`, `pro::v4`, `pro::v5`, …).  When a translation unit sees multiple majors, qualify the namespace explicitly:
```cpp
pro::v3::foo(); // Proxy 3 API
pro::v4::foo(); // Proxy 4 API
pro::v5::foo(); // Proxy 5 API
```
The newest release re-exports its namespace as the inline (default) namespace, so unqualified calls (`pro::foo()`) resolve to the latest version once the migration is complete.
- The macros also have major-qualified aliases, e.g. [`PRO4_DEF_MEM_DISPATCH`](spec/PRO_DEF_MEM_DISPATCH.md). Use these forms whenever headers from multiple majors are included in the same translation unit.
- The macros also have major-qualified aliases, e.g. [`PRO5_DEF_MEM_DISPATCH`](spec/PRO_DEF_MEM_DISPATCH.md). Use these forms whenever headers from multiple majors are included in the same translation unit.
- Upgrade subsystems incrementally, module-by-module or DLL-by-DLL. When every target depends only on the new major, drop the old include path and remove the previous version from your build.

These rules let old and new code coexist during the transition while keeping ODR violations at bay.
Expand Down
2 changes: 1 addition & 1 deletion docs/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ foreach line : _gen.stdout().split('\n')
),
extra_files: md,
implicit_include_directories: false,
dependencies: [msft_proxy4_dep] + extra_deps,
dependencies: [msft_proxy5_dep] + extra_deps,
build_by_default: false,
)
examples += _ex
Expand Down
40 changes: 20 additions & 20 deletions docs/modules_support.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,43 @@ The "Proxy" library ships with `.ixx` files starting with version **4.0.0**. Com
As of 2025-05-11, CMake lacks support for forward compatibility when consuming C++ modules, which causes consumers with newer C++ standard to be unable to use modules with older standard. Until this is implemented by CMake, a CMake target containing the module can be manually declared using the following CMake script:

```cmake
find_package(msft_proxy4 REQUIRED)
find_package(msft_proxy5 REQUIRED)

if(NOT DEFINED msft_proxy4_INCLUDE_DIR) # (1)
if(NOT DEFINED msft_proxy4_SOURCE_DIR)
message(FATAL_ERROR "`msft_proxy4_INCLUDE_DIR` or `msft_proxy4_SOURCE_DIR` must be defined to use this script.")
if(NOT DEFINED msft_proxy5_INCLUDE_DIR) # (1)
if(NOT DEFINED msft_proxy5_SOURCE_DIR)
message(FATAL_ERROR "`msft_proxy5_INCLUDE_DIR` or `msft_proxy5_SOURCE_DIR` must be defined to use this script.")
endif()
set(msft_proxy4_INCLUDE_DIR ${msft_proxy4_SOURCE_DIR}/include)
set(msft_proxy5_INCLUDE_DIR ${msft_proxy5_SOURCE_DIR}/include)
endif()

message(STATUS "Declaring `msft_proxy4::proxy_module` target for include path `${msft_proxy4_INCLUDE_DIR}`")
message(STATUS "Declaring `msft_proxy5::proxy_module` target for include path `${msft_proxy5_INCLUDE_DIR}`")

add_library(msft_proxy4_module)
add_library(msft_proxy5_module)
set_target_properties(
msft_proxy4_module
msft_proxy5_module
PROPERTIES
SYSTEM TRUE
EXCLUDE_FROM_ALL TRUE
)

add_library(msft_proxy4::proxy_module ALIAS msft_proxy4_module)
target_sources(msft_proxy4_module PUBLIC
add_library(msft_proxy5::proxy_module ALIAS msft_proxy5_module)
target_sources(msft_proxy5_module PUBLIC
FILE_SET CXX_MODULES
BASE_DIRS ${msft_proxy4_INCLUDE_DIR}
BASE_DIRS ${msft_proxy5_INCLUDE_DIR}
FILES
${msft_proxy4_INCLUDE_DIR}/proxy/v4/proxy.ixx
${msft_proxy5_INCLUDE_DIR}/proxy/v5/proxy.ixx
)
target_compile_features(msft_proxy4_module PUBLIC cxx_std_20) # (2)
target_link_libraries(msft_proxy4_module PUBLIC msft_proxy4::proxy)
target_compile_features(msft_proxy5_module PUBLIC cxx_std_20) # (2)
target_link_libraries(msft_proxy5_module PUBLIC msft_proxy5::proxy)
```

- (1) `msft_proxy4_INCLUDE_DIR` is automatically declared after `find_package(msft_proxy4)`. CPM uses a slightly different convention where `msft_proxy4_SOURCE_DIR` is declared after `CPMAddPackage`.
- (2) The C++ standard version for `msft_proxy4_module` target should be the same or higher than the consumer CMake target. For example if your project is using C++23 mode, this line should be changed to `cxx_std_23` or `cxx_std_26` / newer standards.
- (1) `msft_proxy5_INCLUDE_DIR` is automatically declared after `find_package(msft_proxy5)`. CPM uses a slightly different convention where `msft_proxy5_SOURCE_DIR` is declared after `CPMAddPackage`.
- (2) The C++ standard version for `msft_proxy5_module` target should be the same or higher than the consumer CMake target. For example if your project is using C++23 mode, this line should be changed to `cxx_std_23` or `cxx_std_26` / newer standards.

It can then be consumed like this:

```cmake
target_link_libraries(main PRIVATE msft_proxy4::proxy_module)
target_link_libraries(main PRIVATE msft_proxy5::proxy_module)
```

## Example
Expand All @@ -60,7 +60,7 @@ module;

export module dictionary;

import proxy.v4; // (3)
import proxy.v5; // (3)

extern "C++" { // (4)
PRO_DEF_MEM_DISPATCH(MemAt, at);
Expand All @@ -79,7 +79,7 @@ Client:
#include <vector>
#include <iostream>

import proxy.v4;
import proxy.v5;
import dictionary;

int main() {
Expand All @@ -92,5 +92,5 @@ int main() {

- (1) This is a traditional header rather than a module. It should be declared in global fragment (after `module` and before `export module`).
- (2) This makes all `PRO_DEF_` macros available. This header file contains only some macros and are therefore very fast to compile.
- (3) `import proxy.v4;` makes all public interfaces from `pro::v4` namespace available in the current translation unit.
- (3) `import proxy.v5;` makes all public interfaces from `pro::v5` namespace available in the current translation unit.
- (4) As of 2025-05-11, clangd requires the accessor struct to be either `export`-ed, or be declared within an `extern "C++"` block, in order to have auto completion working.
Loading
Loading