aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-08-08 12:50:43 +0200
committerEugen Wissner <belka@caraus.de>2026-08-08 12:50:43 +0200
commitae29de96c94e5c582f4424804464cdd29bf2a013 (patch)
tree10936bcf8e4feef83de5f8aed70aab11a1e46668
parenteaf5934f81dcd8ce5705f13b651d7b93ca8c459f (diff)
downloadelna-cpp.tar.gz
Fix GCC 16 compatibility with MacOSHEADcpp
-rw-r--r--README.md4
-rw-r--r--boot/lexer.ll2
-rw-r--r--gcc/gcc/elna-tree.cc4
-rw-r--r--include/elna/boot/result.h14
-rw-r--r--rakelib/gcc.rake70
5 files changed, 73 insertions, 21 deletions
diff --git a/README.md b/README.md
index 71b6a6d..cc1fe52 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ in the `boot/` directory.
## Build
-The frontend requires GCC 15.3.0 (not tested with other versions).
+The frontend requires GCC 16.1.0 (not tested with other versions).
There is also a `Rakefile` that downloads, builds and installs GCC into the
`./build/` subdirectory. The `Rakefile` assumes that ruby and rake, as well as
@@ -30,7 +30,7 @@ rake gcc
by passing `CC` and `CXX` environment variables to rake, e.g.:
```sh
-rake CC=gcc-15 CXX=g++-15 gcc
+rake CC=gcc-16 CXX=g++-16 gcc
```
See `rake -T` for more tasks. The GCC source is under `build/tools`. The
diff --git a/boot/lexer.ll b/boot/lexer.ll
index ba54433..e944560 100644
--- a/boot/lexer.ll
+++ b/boot/lexer.ll
@@ -210,7 +210,7 @@ to {
}
}
0[b|B]{BIGIT}+ {
- std::uint64_t result = strtoull(yytext, NULL, 2);
+ std::uint64_t result = strtoull(yytext + 2, NULL, 2);
if (errno == ERANGE)
{
diff --git a/gcc/gcc/elna-tree.cc b/gcc/gcc/elna-tree.cc
index 10efb90..05690d6 100644
--- a/gcc/gcc/elna-tree.cc
+++ b/gcc/gcc/elna-tree.cc
@@ -299,8 +299,8 @@ namespace elna::gcc
{
auto real_value = std::get<double>(constant_value);
REAL_VALUE_TYPE real;
- constexpr std::size_t bits_size = (sizeof(double) + sizeof(HOST_WIDE_INT) - 1) / sizeof(HOST_WIDE_INT);
- std::array<HOST_WIDE_INT, bits_size> target_bits;
+ constexpr std::size_t bits_size = (sizeof(double) + sizeof(long) - 1) / sizeof(long);
+ std::array<long, bits_size> target_bits;
std::memcpy(target_bits.data(), &real_value, sizeof(real_value));
real_from_target(&real, target_bits.data(), REAL_MODE_FORMAT(TYPE_MODE(elna_float_type_node)));
diff --git a/include/elna/boot/result.h b/include/elna/boot/result.h
index 49e078e..ee73f33 100644
--- a/include/elna/boot/result.h
+++ b/include/elna/boot/result.h
@@ -232,7 +232,12 @@ namespace elna::boot
inline constexpr bool is_signed_v = std::is_same_v<T, std::int8_t>
|| std::is_same_v<T, std::int16_t>
|| std::is_same_v<T, std::int32_t>
- || std::is_same_v<T, std::int64_t>;
+ || std::is_same_v<T, std::int64_t>
+ || std::is_same_v<T, signed char>
+ || std::is_same_v<T, signed short>
+ || std::is_same_v<T, signed int>
+ || std::is_same_v<T, signed long>
+ || std::is_same_v<T, signed long long>;
/**
* Checks whether \p T is a signed, std::uint*_t type.
@@ -245,7 +250,12 @@ namespace elna::boot
inline constexpr bool is_unsigned_v = std::is_same_v<T, std::uint8_t>
|| std::is_same_v<T, std::uint16_t>
|| std::is_same_v<T, std::uint32_t>
- || std::is_same_v<T, std::uint64_t>;
+ || std::is_same_v<T, std::uint64_t>
+ || std::is_same_v<T, unsigned char>
+ || std::is_same_v<T, unsigned short>
+ || std::is_same_v<T, unsigned int>
+ || std::is_same_v<T, unsigned long>
+ || std::is_same_v<T, unsigned long long>;
/**
* Checks whether \p T is any of std::int*_t or std::uint*_t types.
diff --git a/rakelib/gcc.rake b/rakelib/gcc.rake
index 558c8a2..7b6bf44 100644
--- a/rakelib/gcc.rake
+++ b/rakelib/gcc.rake
@@ -3,11 +3,36 @@
# obtain one at https://mozilla.org/MPL/2.0/. -}
# frozen_string_literal: true
+require 'fileutils'
require 'uri'
require 'net/http'
require 'open3'
require 'pathname'
+# Use Homebrew GCC if available (it uses libstdc++, avoiding
+# macOS-specific libc++ incompatibilities in GCC's own sources).
+class GCCConfiguration
+ attr_reader :target
+
+ def initialize(suffix, target, sysroot_sdk)
+ @suffix = suffix
+ @target = target
+ @sysroot_sdk = sysroot_sdk
+ end
+
+ def cc
+ "gcc#{@suffix}"
+ end
+
+ def cxx
+ "g++#{@suffix}"
+ end
+
+ def configure
+ @sysroot_sdk.nil? ? [] : ["--with-sysroot=#{@sysroot_sdk}"]
+ end
+end
+
def gcc_verbose(gcc_binary)
read, write = IO.pipe
sh({'LC_ALL' => 'C'}, gcc_binary, '--verbose', err: write)
@@ -17,13 +42,21 @@ def gcc_verbose(gcc_binary)
output
end
-def find_build_target
- gcc_verbose(ENV.fetch 'CC', 'gcc')
+def find_build_target(gcc_version)
+ if RUBY_PLATFORM =~ /darwin/
+ suffix = '-' + gcc_version.split('.').first
+ mac_os_sdk = '/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk'
+ else
+ suffix = ''
+ end
+ build_target = gcc_verbose(ENV.fetch 'CC', "gcc#{suffix}")
.lines
.find { |line| line.start_with? 'Target: ' }
.split(' ')
.last
.strip
+
+ GCCConfiguration.new suffix, build_target, mac_os_sdk
end
def download_and_pipe(url, target, command)
@@ -66,11 +99,12 @@ namespace :gcc do
# Dependencies.
GCC_VERSION = "16.1.0"
HOST_GCC = 'build/host/gcc'
+ HOST_INSTALL = Pathname.new 'build/host/install'
GCC_TREE = Pathname.new "build/tools/gcc-#{GCC_VERSION}"
GCC_PATCH = 'https://raw.githubusercontent.com/Homebrew/homebrew-core/refs/heads/main/Patches/gcc/gcc-16.1.0.diff'
directory HOST_GCC
- directory 'build/host/install'
+ directory HOST_INSTALL.to_path
directory 'build/tools'
desc 'Download the bootstrap compiler and its prerequisites'
@@ -81,7 +115,7 @@ namespace :gcc do
download_and_pipe URI.parse(GCC_PATCH), GCC_TREE, ['patch', '-p1']
# GCC 16.1.0 registers 17 languages but CL_PARAMS is at bit 16,
- # which collides with the 17th language class (CL_Rust). Shift
+ # which collides with the 17th language class (CL_Rust). Shift
# every CL_* constant from bit 16 upward by one position.
File.open(GCC_TREE + 'gcc/opts.h', 'r+') do |opts_h|
content = opts_h.read.gsub(/\(1U << (\d+)\)/) do |m|
@@ -116,8 +150,8 @@ namespace :gcc do
end
desc 'Configure the bootstrap compiler'
- task configure: [HOST_GCC, 'build/host/install'] do |t|
- build_target = find_build_target
+ task configure: [HOST_GCC, HOST_INSTALL.to_path] do |t|
+ build_target = find_build_target GCC_VERSION
configure_options = [
"--prefix=#{File.realpath t.prerequisites.last}",
'--enable-languages=c,c++,jit,elna',
@@ -125,14 +159,15 @@ namespace :gcc do
'--disable-multilib',
'--enable-host-shared',
'--with-system-zlib',
- "--target=#{build_target}",
- "--build=#{build_target}",
- "--host=#{build_target}"
+ "--target=#{build_target.target}",
+ "--build=#{build_target.target}",
+ "--host=#{build_target.target}",
+ *build_target.configure
]
- mac_os_sdk = '/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk'
- configure_options << "--with-sysroot=#{mac_os_sdk}" if File.symlink? mac_os_sdk
-
- env = ENV.slice 'CC', 'CXX'
+ env = {
+ 'CC' => ENV['CC'] || build_target.cc,
+ 'CXX' => ENV['CXX'] || build_target.cxx
+ }
env['CFLAGS'] = env['CXXFLAGS'] = '-O0 -g -fPIC -I/opt/homebrew/opt/flex/include'
configure = GCC_TREE.relative_path_from(HOST_GCC) + 'configure'
@@ -163,7 +198,14 @@ namespace :gcc do
.reject do |file|
['/elna1.', '/elna-spec.'].any? { |pattern| file.include? pattern }
end
- sh 'clang-tidy', '-p', compile_db.to_path, '--extra-arg=-w', '--warnings-as-errors=*', *sources
+ build_target = find_build_target GCC_VERSION
+ includes = ['.', build_target.target].collect do |inc|
+ HOST_INSTALL + 'include/c++' + GCC_VERSION + inc
+ end
+
+ sh 'clang-tidy', '-p', compile_db.to_path, '--extra-arg=-w', '--warnings-as-errors=*',
+ *includes.collect { |inc| "--extra-arg=-cxx-isystem#{inc.realpath}" },
+ '--extra-arg=-stdlib=libstdc++', *sources
end
desc 'Build documentation'