Skip to content

Commit cae91b2

Browse files
authored
[SYCL] Import/preprocess boost/mp11 at build time to use in SYCL headers. (#5791)
* [SYCL] Import/preprocess boost/mp11 at build time to use in SYCL headers. Preprocessing adapts boost/mp11 headers for use in SYCL headers in a way that does not conflict with potential use of boost in user code. Particularly, `BOOST_*` macros are replaced with `SYCL_BOOST_*`, APIs are moved into the top-level `sycl` namespace. For example, `sycl::boost::mp11::mp_list`. Signed-off-by: Konstantin S Bobrovsky <[email protected]>
1 parent e25f199 commit cae91b2

File tree

4 files changed

+215
-1
lines changed

4 files changed

+215
-1
lines changed

sycl/CMakeLists.txt

+6-1
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ configure_file("${version_header}.in" "${version_header}")
142142
set(feature_header "${sycl_inc_dir}/CL/sycl/feature_test.hpp")
143143
configure_file("${feature_header}.in" "${feature_header}")
144144

145+
include(AddBoostMp11Headers)
146+
145147
# This is workaround to detect changes (add or modify) in subtree which
146148
# are not detected by copy_directory command.
147149
# TODO: detect and process remove header/directory case
@@ -159,7 +161,8 @@ string(REPLACE "${sycl_inc_dir}" "${SYCL_INCLUDE_BUILD_DIR}"
159161
add_custom_target(sycl-headers
160162
DEPENDS ${OUT_HEADERS_IN_SYCL_DIR}
161163
${OUT_HEADERS_IN_CL_DIR}
162-
${OUT_HEADERS_IN_STD_DIR})
164+
${OUT_HEADERS_IN_STD_DIR}
165+
boost_mp11-headers)
163166

164167
add_custom_command(
165168
OUTPUT ${OUT_HEADERS_IN_SYCL_DIR}
@@ -177,6 +180,7 @@ add_custom_command(
177180
install(DIRECTORY "${sycl_inc_dir}/sycl" DESTINATION ${SYCL_INCLUDE_DIR} COMPONENT sycl-headers)
178181
install(DIRECTORY "${sycl_inc_dir}/CL" DESTINATION ${SYCL_INCLUDE_DIR}/sycl COMPONENT sycl-headers)
179182
install(DIRECTORY "${sycl_inc_dir}/std" DESTINATION ${SYCL_INCLUDE_DIR} COMPONENT sycl-headers)
183+
install(DIRECTORY ${BOOST_MP11_DESTINATION_DIR} DESTINATION ${SYCL_INCLUDE_DIR}/sycl COMPONENT boost_mp11-headers)
180184

181185
set(SYCL_RT_LIBS sycl)
182186
if (MSVC)
@@ -315,6 +319,7 @@ endif()
315319
# Listed here are component names contributing the package
316320
set( SYCL_TOOLCHAIN_DEPLOY_COMPONENTS
317321
append-file
322+
boost_mp11-headers
318323
clang
319324
clang-offload-wrapper
320325
clang-offload-bundler
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# boost/mp11 headers import and preprocessing
2+
# See more comments in cmake/modules/PreprocessBoostMp11Headers.cmake
3+
4+
include(FetchContent)
5+
6+
set(BOOST_MP11_GIT_REPO https://github.com/boostorg/mp11.git)
7+
# Author: pdimov
8+
# Date: Feb 16, 2022
9+
# Comment:
10+
# Merge pull request #71 from grisumbras/feature/mp_valid_and_true
11+
set(BOOST_MP11_GIT_TAG 7bc4e1ae9b36ec8ee635c3629b59ec525bbe82b9)
12+
13+
# Either download from github or use existing if BOOST_MP11_SOURCE_DIR is set
14+
if (NOT DEFINED BOOST_MP11_SOURCE_DIR)
15+
message(STATUS "BOOST_MP11_SOURCE_DIR not set, downloading boost/mp11 headers from ${BOOST_MP11_GIT_REPO}")
16+
17+
FetchContent_Declare(boost_mp11
18+
GIT_REPOSITORY ${BOOST_MP11_GIT_REPO}
19+
GIT_TAG ${BOOST_MP11_GIT_TAG}
20+
)
21+
FetchContent_GetProperties(boost_mp11)
22+
FetchContent_MakeAvailable(boost_mp11)
23+
24+
set(BOOST_MP11_SOURCE_DIR ${boost_mp11_SOURCE_DIR})
25+
set(BOOST_MP11_SRC_PATH ${BOOST_MP11_GIT_REPO})
26+
set(BOOST_MP11_SRC_ID "git commit hash: ${BOOST_MP11_GIT_TAG}")
27+
else (NOT DEFINED BOOST_MP11_SOURCE_DIR)
28+
message(STATUS "Using boost/mp11 headers from ${BOOST_MP11_SOURCE_DIR}")
29+
set(BOOST_MP11_SRC_PATH ${BOOST_MP11_SOURCE_DIR})
30+
set(BOOST_MP11_SRC_ID "ID not set")
31+
endif(NOT DEFINED BOOST_MP11_SOURCE_DIR)
32+
33+
# Read all header file names into HEADERS_BOOST_MP11
34+
file(GLOB_RECURSE HEADERS_BOOST_MP11 CONFIGURE_DEPENDS "${BOOST_MP11_SOURCE_DIR}/include/boost/*")
35+
36+
set(BOOST_MP11_DESTINATION_DIR ${SYCL_INCLUDE_BUILD_DIR}/sycl/detail/boost)
37+
string(REPLACE "${BOOST_MP11_SOURCE_DIR}/include/boost" "${BOOST_MP11_DESTINATION_DIR}"
38+
OUT_HEADERS_BOOST_MP11 "${HEADERS_BOOST_MP11}")
39+
40+
# The target which produces preprocessed boost/mp11 headers
41+
add_custom_target(boost_mp11-headers
42+
DEPENDS ${OUT_HEADERS_BOOST_MP11})
43+
44+
# Run preprocessing on each header, output result into
45+
# ${BOOST_MP11_DESTINATION_DIR}
46+
add_custom_command(
47+
OUTPUT ${OUT_HEADERS_BOOST_MP11}
48+
DEPENDS ${HEADERS_BOOST_MP11}
49+
COMMAND ${CMAKE_COMMAND}
50+
-DIN=${BOOST_MP11_SOURCE_DIR}/include/boost
51+
-DOUT=${BOOST_MP11_DESTINATION_DIR}
52+
-DSRC_PATH="${BOOST_MP11_SRC_PATH}"
53+
-DSRC_ID="${BOOST_MP11_SRC_ID}"
54+
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/PreprocessBoostMp11Headers.cmake
55+
COMMENT "Preprocessing boost/mp11 headers ${BOOST_MP11_SOURCE_DIR}/include/boost -> ${BOOST_MP11_DESTINATION_DIR}...")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Preprocess boost/mp11 headers to allow using specific version of mp11 (as
2+
# defined in these project's cmake files) within SYCL library w/o risk of
3+
# conflict with user program using another version of boost/mp11. Basically,
4+
# this transformation moves all APIs from boost namespace to sycl::boost and
5+
# adds SYCL_ prefix to boost macros names. See more specific comments in the
6+
# code below.
7+
# Variables which must be set by the caller to control behavior of this module:
8+
# - IN
9+
# The source directory with mp11 headers, must contain mp11.h.
10+
# - OUT
11+
# The destination directory where preprocessed source headers are put.
12+
# - SRC_PATH
13+
# An URL or directory name the source directory originates from. Used only in
14+
# generated README text.
15+
# - SRC_ID
16+
# Git hash/tag or other ID identifying the original source. Used only in
17+
# generated README text.
18+
#
19+
# Assumed to be invoked as a script:
20+
# ${CMAKE_COMMAND} -DIN=... -DOUT=... -DSRC_PATH=... -DSRC_ID=... -P <this file>
21+
22+
function(preprocess_mp11_header)
23+
cmake_parse_arguments(
24+
MP11_HDR # prefix
25+
"" # options
26+
"SRC_NAME;DST_NAME;IN_DIR" # one value keywords
27+
"" # multi-value keywords
28+
${ARGN}) # arguments
29+
file(READ ${MP11_HDR_SRC_NAME} FILE_CONTENTS)
30+
31+
# 1) replace `BOOST_*` macros with `SYCL_BOOST_*`.
32+
string(REGEX REPLACE
33+
"([ \t\n\r!])BOOST_"
34+
"\\1SYCL_DETAIL_BOOST_"
35+
FILE_CONTENTS "${FILE_CONTENTS}")
36+
# 2) replace `namespace boost { ... }` with
37+
# `namespace sycl { namespace detail { namespace boost { ... } } }`
38+
string(REGEX REPLACE
39+
"(\n[ \t]*namespace[ \t\n\r]+boost)"
40+
"namespace sycl\n{\nnamespace detail\n{\\1"
41+
FILE_CONTENTS "${FILE_CONTENTS}")
42+
# ... use '} // namespace boost' as a marker for end-of-scope '}' replacement
43+
string(REGEX REPLACE
44+
"(\n[ \t]*}[ \t]*//[ \t]*namespace[ \t]+boost[ \t]*\n)"
45+
"\\1} // namespace detail\n} // namespace sycl\n"
46+
FILE_CONTENTS "${FILE_CONTENTS}")
47+
# 3) replace `boost` in `#include <boost/...>` or `#include "boost/..."` with
48+
# `sycl/detail/boost`
49+
string(REGEX REPLACE
50+
"(\n#include[ \t]*[<\"])boost"
51+
"\\1sycl/detail/boost"
52+
FILE_CONTENTS "${FILE_CONTENTS}")
53+
54+
set(SYCL_DERIVED_COPYRIGHT_NOTICE "\
55+
// -*- C++ -*-\n\
56+
//===----------------------------------------------------------------------===//\n\
57+
// Modifications Copyright Intel Corporation 2022\n\
58+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\
59+
//===----------------------------------------------------------------------===//\n\
60+
// Auto-generated from boost/mp11 sources https://github.com/boostorg/mp11\n\n")
61+
62+
# 4) add proper copyright notice atop
63+
string(PREPEND FILE_CONTENTS ${SYCL_DERIVED_COPYRIGHT_NOTICE})
64+
file(WRITE ${MP11_HDR_DST_NAME} "${FILE_CONTENTS}")
65+
endfunction(preprocess_mp11_header)
66+
67+
function(preprocess_mp11_headers)
68+
cmake_parse_arguments(
69+
MP11_HDRS # prefix
70+
"" # options
71+
"IN;OUT;SRC_PATH;SRC_ID" # one value keywords
72+
"" # multi-value keywords
73+
${ARGN}) # arguments
74+
75+
# 1) Perform necessary preprocessing of headers.
76+
file(GLOB_RECURSE BOOST_MP11_SOURCES "${MP11_HDRS_IN}/*")
77+
78+
foreach(SRC ${BOOST_MP11_SOURCES})
79+
string(REPLACE "${MP11_HDRS_IN}" "${MP11_HDRS_OUT}" DST "${SRC}")
80+
preprocess_mp11_header(
81+
SRC_NAME ${SRC}
82+
DST_NAME ${DST}
83+
IN_DIR ${MP11_HDRS_IN}
84+
)
85+
endforeach(SRC ${BOOST_MP11_SOURCES})
86+
87+
# 2) Add SYCL_README.txt to the output directory root
88+
set(SYCL_README_TEXT "\
89+
This directory contains boost/mp11 headers imported from\n\
90+
${MP11_HDRS_SRC_PATH} (${MP11_HDRS_SRC_ID})\n\
91+
and adapted for use in SYCL headers in a way that does not conflict with\n\
92+
potential use of boost in user code. Particularly, `BOOST_*` macros are\n\
93+
replaced with `SYCL_DETAIL_BOOST_*`, APIs are moved into the top-level
94+
`sycl::detail` namespace. For example, `sycl::detail::boost::mp11::mp_list`.\n")
95+
96+
set(SYCL_README_FILE_NAME "${MP11_HDRS_OUT}/README.txt")
97+
98+
file(WRITE ${SYCL_README_FILE_NAME} "${SYCL_README_TEXT}")
99+
endfunction(preprocess_mp11_headers)
100+
101+
preprocess_mp11_headers(
102+
IN ${IN}
103+
OUT ${OUT}
104+
SRC_PATH ${SRC_PATH}
105+
SRC_ID ${SRC_ID}
106+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
// Modifications Copyright Intel Corporation 2022
4+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
//===----------------------------------------------------------------------===//
6+
// Based on boost/mp11 tests obtained from
7+
// https://github.com/boostorg/mp11/blob/develop/test/mp_fill.cpp
8+
// (git commit a231733).
9+
10+
//===----------------------------------------------------------------------===//
11+
// Copyright 2015 Peter Dimov.
12+
//
13+
// Distributed under the Boost Software License, Version 1.0.
14+
//
15+
// See accompanying file LICENSE_1_0.txt or copy at
16+
// http://www.boost.org/LICENSE_1_0.txt
17+
//===----------------------------------------------------------------------===//
18+
19+
// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple -c %s
20+
21+
// This is a sanity check test to verify that the automatic boost/mp11 import
22+
// into SYCL is not badly broken.
23+
24+
#include <type_traits>
25+
26+
#include <sycl/detail/boost/mp11.hpp>
27+
28+
struct X1 {};
29+
30+
int main() {
31+
using sycl::detail::boost::mp11::mp_fill;
32+
using sycl::detail::boost::mp11::mp_list;
33+
34+
using L1 = mp_list<int, void(), float[]>;
35+
static_assert(std::is_same_v<mp_fill<L1, X1>, mp_list<X1, X1, X1>>);
36+
37+
//
38+
39+
using L2 = std::tuple<int, char, float>;
40+
static_assert(std::is_same_v<mp_fill<L2, X1>, std::tuple<X1, X1, X1>>);
41+
42+
//
43+
44+
using L3 = std::pair<char, double>;
45+
static_assert(std::is_same_v<mp_fill<L3, X1>, std::pair<X1, X1>>);
46+
47+
return 0;
48+
}

0 commit comments

Comments
 (0)