gcc/contrib/relpath.sh
Jason Merrill 7db55c0ba1 libstdc++: add module std [PR106852]
This patch introduces an installed source form of module std and std.compat.
To help a build system find them, we install a libstdc++.modules.json file
alongside libstdc++.so, which tells the build system where the files are and
any special flags it should use when compiling them (none, in this case).
The format is from a proposal in SG15.  The build system can find this file
with 'gcc -print-file-name=libstdc++.modules.json'.

It seems preferable to use a relative path from this file to the sources so
that moving the installation doesn't break the reference, but I didn't see
any obvious way to compute that without relying on coreutils, perl, or
python, so I wrote a POSIX shell script for it.  The .. canonicalization
bits aren't necessary since I discovered $(abspath), but I guess I might as
well leave them in.

Currently this installs the sources under $(gxx_include_dir)/bits/,
i.e. /usr/include/c++/15/bits.  So with my -fsearch-include-path change,
std.cc can be compiled with g++ -fsearch-include-path bits/std.cc.  Note
that if someone actually tries to #include <bits/std.cc> it will fail with
"error: module control-line cannot be in included file".

Any ideas about a more user-friendly way to express "compile module std" are
welcome.

The sources currently have the extension .cc, like other source files.

std.cc started with m.cencora's implementation in PR114600.  I've made some
adjustments, but more is probably desirable, e.g. of the <algorithm>
handling of namespace ranges, and to remove exports of templates that are
only specialized in a particular header.  I've filled in a bunch of missing
exports, and added some FIXMEs where I noticed bits that are not implemented
yet.

Since bits/stdc++.h also intends to include the whole standard library, I
include it rather than duplicate it.  But stdc++.h comments out <execution>,
due to TBB issues; I include it separately and suppress TBB usage, so module
std won't currently provide parallel execution.

It seemed most convenient for the two files to be monolithic so we don't
need to worry about include paths.  So the C library names that module
std.compat exports in both namespace std and :: are a block of code that is
appended to both files, adjusted based on whether the macro STD_COMPAT is
defined before the block.

In this implementation std.compat imports std; it would also be valid for it
to duplicate everything in std.  I see the libc++ std.compat also imports
std.

As discussed in the PR, module std is supported in C++20 mode even though it
was added in C++23.

Changes to test module std will follow in a separate patch.  In my testing
I've noticed a few compiler bugs that break various testcases, so I don't
expect to enable module std testing by default at first.

	PR libstdc++/106852

libstdc++-v3/ChangeLog:

	* include/bits/version.def: Add __cpp_lib_modules.
	* include/bits/version.h: Regenerate.
	* src/c++23/Makefile.am: Add modules std and std.compat.
	* src/c++23/Makefile.in: Regenerate.
	* src/c++23/std-clib.cc.in: New file.
	* src/c++23/std.cc.in: New file.
	* src/c++23/std.compat.cc.in: New file.
	* src/c++23/libstdc++.modules.json.in: New file.

contrib/ChangeLog:

	* relpath.sh: New file.
2024-11-17 16:23:21 +01:00

82 lines
1.4 KiB
Bash
Executable File

#!/bin/sh
if [ "$1" = "--help" -o $# -ne 2 -o -f "$1" ]; then
echo Usage: relpath.sh FROM TO
echo Print the relative path from FROM to TO
echo FROM must be a directory, but need not exist
exit 0
fi
from="${1%%/}"
to="${2%%/}"
# The parent directory of a pathname, handling ..
parent() {
name=$(basename "$1")
path=$(dirname "$1")
top=$(basename "$path")
if [ "$top" = ".." ]; then
path=$(parent "$path")
fi
if [ "$name" = ".." ]; then
path=$(parent "$path")
fi
echo $path
}
# Canonicalize a directory that contains '..'.
canonicalize() {
path=$1
suffix=
while ! [ -d "$path" ]; do
name=$(basename "$path")
path=$(parent "$path")
suffix="/$name$suffix"
done
if [ -d "$path" ]; then
echo $(cd "$path"; pwd)$suffix
else
echo $1
fi
}
case "$to$from" in
*..* )
from=$(canonicalize "$from")
to=$(canonicalize "$to")
;;
esac
case "$to$from" in
*..* )
echo unable to canonicalize .. >&2
exit 1
;;
esac
back=
while [ "${to#$from}" = "$to" ]; do
#echo $from too long
from=$(dirname $from);
back=../$back
if [ "$from" = "/" ]; then
echo $to
exit 0
elif [ "$from" = . ]; then
echo no common ancestor between $1 and $2 >&2
exit 1
fi
done
to=${to#$from}
to=${to##/}
back=${back%%/}
if [ -n "$to" ] && [ -n "$back" ]; then
echo $back/$to
elif [ -n "$back$to" ]; then
echo $back$to
else
echo .
fi