Skip to content

Commit 0d20a98

Browse files
committed
Make it compile on Ubuntu, with some pain
1 parent 4a2bd58 commit 0d20a98

5 files changed

Lines changed: 202 additions & 120 deletions

File tree

plugins/header_rewrite/header_rewrite.cc

Lines changed: 12 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -70,67 +70,20 @@ initHRWLibraries(const std::string &dbPath)
7070
// Forward declaration for the main continuation.
7171
static int cont_rewrite_headers(TSCont, TSEvent, void *);
7272

73-
// Simple wrapper around a configuration file / set. This is useful such that
74-
// we can reuse most of the code for both global and per-remap rule sets.
75-
class RulesConfig
76-
{
77-
public:
78-
RulesConfig(int timezone, int inboundIpSource) : _timezone(timezone), _inboundIpSource(inboundIpSource)
79-
{
80-
Dbg(dbg_ctl, "RulesConfig CTOR");
81-
_cont = TSContCreate(cont_rewrite_headers, nullptr);
82-
TSContDataSet(_cont, static_cast<void *>(this));
83-
}
84-
85-
~RulesConfig()
86-
{
87-
Dbg(dbg_ctl, "RulesConfig DTOR");
88-
TSContDestroy(_cont);
89-
}
90-
91-
[[nodiscard]] TSCont
92-
continuation() const
93-
{
94-
return _cont;
95-
}
73+
#include "rules_config.h"
9674

97-
[[nodiscard]] ResourceIDs
98-
resid(int hook) const
99-
{
100-
return _resids[hook];
101-
}
102-
103-
[[nodiscard]] RuleSet *
104-
rule(int hook) const
105-
{
106-
return _rules[hook].get();
107-
}
108-
109-
[[nodiscard]] int
110-
timezone() const
111-
{
112-
return _timezone;
113-
}
114-
115-
[[nodiscard]] int
116-
inboundIpSource() const
117-
{
118-
return _inboundIpSource;
119-
}
120-
121-
bool parse_config(const std::string &fname, TSHttpHookID default_hook, char *from_url = nullptr, char *to_url = nullptr,
122-
bool force_hrw4u = false);
123-
124-
private:
125-
void add_rule(std::unique_ptr<RuleSet> rule);
126-
127-
TSCont _cont;
128-
std::array<std::unique_ptr<RuleSet>, TS_HTTP_LAST_HOOK + 1> _rules{};
129-
std::array<ResourceIDs, TS_HTTP_LAST_HOOK + 1> _resids{};
75+
RulesConfig::RulesConfig(int timezone, int inboundIpSource) : _timezone(timezone), _inboundIpSource(inboundIpSource)
76+
{
77+
Dbg(dbg_ctl, "RulesConfig CTOR");
78+
_cont = TSContCreate(cont_rewrite_headers, nullptr);
79+
TSContDataSet(_cont, static_cast<void *>(this));
80+
}
13081

131-
int _timezone = 0;
132-
int _inboundIpSource = 0;
133-
};
82+
RulesConfig::~RulesConfig()
83+
{
84+
Dbg(dbg_ctl, "RulesConfig DTOR");
85+
TSContDestroy(_cont);
86+
}
13487

13588
void
13689
RulesConfig::add_rule(std::unique_ptr<RuleSet> rule)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
#pragma once
20+
21+
#include <array>
22+
#include <memory>
23+
#include <string>
24+
25+
#include "ts/ts.h"
26+
#include "ruleset.h"
27+
#include "resources.h"
28+
29+
class RulesConfig
30+
{
31+
public:
32+
RulesConfig(int timezone, int inboundIpSource);
33+
~RulesConfig();
34+
35+
bool parse_config(const std::string &fname, TSHttpHookID default_hook, char *from_url = nullptr, char *to_url = nullptr,
36+
bool force_hrw4u = false);
37+
38+
[[nodiscard]] TSCont
39+
continuation() const
40+
{
41+
return _cont;
42+
}
43+
44+
[[nodiscard]] ResourceIDs
45+
resid(int hook) const
46+
{
47+
return _resids[hook];
48+
}
49+
50+
[[nodiscard]] RuleSet *
51+
rule(int hook) const
52+
{
53+
return _rules[hook].get();
54+
}
55+
56+
[[nodiscard]] int
57+
timezone() const
58+
{
59+
return _timezone;
60+
}
61+
62+
[[nodiscard]] int
63+
inboundIpSource() const
64+
{
65+
return _inboundIpSource;
66+
}
67+
68+
private:
69+
void add_rule(std::unique_ptr<RuleSet> rule);
70+
71+
TSCont _cont;
72+
std::array<std::unique_ptr<RuleSet>, TS_HTTP_LAST_HOOK + 1> _rules{};
73+
std::array<ResourceIDs, TS_HTTP_LAST_HOOK + 1> _resids{};
74+
75+
int _timezone = 0;
76+
int _inboundIpSource = 0;
77+
};

src/hrw4u/CMakeLists.txt

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#
1616
#######################
1717

18-
# Find ANTLR4 runtime
1918
find_package(antlr4-runtime QUIET)
2019

2120
if(NOT antlr4-runtime_FOUND)
@@ -27,7 +26,6 @@ if(NOT antlr4-runtime_FOUND)
2726
return()
2827
endif()
2928

30-
# Find ANTLR4 generator tool
3129
find_program(ANTLR4_EXECUTABLE antlr4 NAMES antlr4 antlr)
3230

3331
if(NOT ANTLR4_EXECUTABLE)
@@ -39,22 +37,55 @@ if(NOT ANTLR4_EXECUTABLE)
3937
return()
4038
endif()
4139

42-
# ANTLR4 available - hrw4u will be built
40+
# Verify tool version matches runtime (ANTLR4 C++ API breaks between minor versions).
41+
if(ANTLR_VERSION)
42+
execute_process(
43+
COMMAND ${ANTLR4_EXECUTABLE}
44+
OUTPUT_VARIABLE _antlr4_tool_stdout
45+
ERROR_VARIABLE _antlr4_tool_stderr
46+
OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE
47+
TIMEOUT 10
48+
)
49+
set(_antlr4_tool_output "${_antlr4_tool_stdout} ${_antlr4_tool_stderr}")
50+
string(REGEX MATCH "[Vv]ersion[ \t]+([0-9]+\\.[0-9]+\\.?[0-9]*)" _antlr4_version_match "${_antlr4_tool_output}")
51+
set(_antlr4_tool_version "${CMAKE_MATCH_1}")
52+
unset(_antlr4_tool_stdout)
53+
unset(_antlr4_tool_stderr)
54+
unset(_antlr4_tool_output)
55+
unset(_antlr4_version_match)
56+
57+
if(_antlr4_tool_version)
58+
string(REGEX MATCH "^([0-9]+\\.[0-9]+)" _tool_major_minor "${_antlr4_tool_version}")
59+
string(REGEX MATCH "^([0-9]+\\.[0-9]+)" _runtime_major_minor "${ANTLR_VERSION}")
60+
if(NOT _tool_major_minor STREQUAL _runtime_major_minor)
61+
message(WARNING "ANTLR4 version mismatch: tool is ${_antlr4_tool_version}, runtime is ${ANTLR_VERSION}. "
62+
"hrw4u will not be built. Install matching versions to enable hrw4u."
63+
)
64+
set(TS_HAS_CPP_HRW4U
65+
FALSE
66+
PARENT_SCOPE
67+
)
68+
return()
69+
endif()
70+
message(STATUS "ANTLR4 tool version ${_antlr4_tool_version} matches runtime ${ANTLR_VERSION}")
71+
unset(_tool_major_minor)
72+
unset(_runtime_major_minor)
73+
else()
74+
message(STATUS "Could not determine ANTLR4 tool version, proceeding with runtime ${ANTLR_VERSION}")
75+
endif()
76+
unset(_antlr4_tool_version)
77+
endif()
78+
4379
set(TS_HAS_CPP_HRW4U
4480
TRUE
4581
PARENT_SCOPE
4682
)
47-
4883
message(STATUS "Building hrw4u library with ANTLR4 support")
4984

50-
# Grammar file location
5185
set(HRW4U_GRAMMAR_FILE "${PROJECT_SOURCE_DIR}/tools/hrw4u/grammar/hrw4u.g4")
52-
53-
# Generated parser output directory
5486
set(HRW4U_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
5587
file(MAKE_DIRECTORY ${HRW4U_GENERATED_DIR})
5688

57-
# Generate C++ parser from grammar
5889
set(HRW4U_GENERATED_SOURCES ${HRW4U_GENERATED_DIR}/hrw4uLexer.cpp ${HRW4U_GENERATED_DIR}/hrw4uParser.cpp
5990
${HRW4U_GENERATED_DIR}/hrw4uBaseVisitor.cpp ${HRW4U_GENERATED_DIR}/hrw4uVisitor.cpp
6091
)
@@ -73,19 +104,14 @@ add_custom_command(
73104

74105
add_custom_target(hrw4u_generated DEPENDS ${HRW4U_GENERATED_SOURCES})
75106

76-
# Suppress warnings for generated ANTLR4 code
77107
set_source_files_properties(${HRW4U_GENERATED_SOURCES} PROPERTIES COMPILE_FLAGS "-Wno-unused-parameter")
78108

79-
# Library sources
80109
set(HRW4U_SOURCES Error.cc Types.cc Tables.cc Visitor.cc HRW4UVisitorImpl.cc)
81110

82-
# Create static library
83111
add_library(hrw4u STATIC ${HRW4U_SOURCES} ${HRW4U_GENERATED_SOURCES})
84112
add_library(ts::hrw4u ALIAS hrw4u)
85113

86-
# GCC treats out-of-order and missing designated initializers as errors under
87-
# -Werror. The hrw4u tables use Clang-style designated initializers that rely
88-
# on default member values, which is safe but upsets GCC.
114+
# GCC errors on Clang-style designated initializers under -Werror.
89115
target_compile_options(hrw4u PRIVATE -Wno-missing-field-initializers)
90116
set_target_properties(hrw4u PROPERTIES POSITION_INDEPENDENT_CODE ON)
91117

@@ -97,12 +123,16 @@ target_include_directories(
97123
PRIVATE ${HRW4U_GENERATED_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
98124
)
99125

100-
# Prefer static ANTLR4, fall back to shared if unavailable.
101-
if(TARGET antlr4_static)
102-
target_link_libraries(hrw4u PUBLIC antlr4_static)
103-
else()
126+
# Prefer shared ANTLR4 runtime (distro static libs may lack -fPIC).
127+
if(TARGET antlr4_shared)
104128
target_link_libraries(hrw4u PUBLIC antlr4_shared)
105-
target_include_directories(hrw4u PRIVATE ${ANTLR4_INCLUDE_DIR})
129+
elseif(TARGET antlr4_static)
130+
target_link_libraries(hrw4u PUBLIC antlr4_static)
131+
endif()
132+
133+
# Fallback for distro packages that don't set INTERFACE_INCLUDE_DIRECTORIES.
134+
if(ANTLR4_INCLUDE_DIR)
135+
target_include_directories(hrw4u PUBLIC ${ANTLR4_INCLUDE_DIR})
106136
endif()
107137

108138
set(HRW4U_PUBLIC_HEADERS

tools/hrw4u/README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,73 @@ Decompiles existing `header_rewrite` rules back into HRW4U source code.
2121

2222
## Requirements
2323

24+
### Python Tools (hrw4u, u4wrh)
2425
- **Python 3.11+** (uses modern type annotations and performance features)
2526
- **ANTLR4** for grammar parsing
2627
- **uv** (for Python environment management)
2728

29+
### C++ Native Parser (src/hrw4u)
30+
31+
ATS includes a C++ ANTLR4-based parser that lets the `header_rewrite` plugin
32+
load `.hrw4u` files directly. Building it requires:
33+
34+
- **ANTLR4 C++ runtime** (headers and shared library)
35+
- **ANTLR4 tool** (`antlr4` command, same major.minor version as the runtime)
36+
37+
#### macOS (Homebrew)
38+
```bash
39+
brew install antlr4-cpp-runtime antlr4
40+
```
41+
42+
#### Fedora/RHEL
43+
```bash
44+
dnf install antlr4-cpp-runtime-devel antlr4
45+
```
46+
47+
#### Ubuntu/Debian (from source recommended)
48+
49+
The distro packages often have version mismatches between the tool and runtime,
50+
and the shared library may be built with a different C++ ABI. Building from
51+
source is recommended:
52+
53+
```bash
54+
# Download ANTLR4 C++ runtime source (match JAR version)
55+
# https://github.com/antlr/antlr4/releases
56+
57+
cd antlr4-cpp-runtime-<version>
58+
cmake -B build \
59+
-DCMAKE_INSTALL_PREFIX=/opt/antlr4 \
60+
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
61+
-DANTLR4_INSTALL=ON
62+
cmake --build build -j$(nproc)
63+
cmake --install build
64+
```
65+
66+
If you are building ATS with a non-default compiler toolchain, build the
67+
ANTLR4 runtime with the same compilers to avoid ABI mismatches:
68+
69+
```bash
70+
cmake -B build \
71+
-DCMAKE_C_COMPILER=/opt/llvm/bin/clang \
72+
-DCMAKE_CXX_COMPILER=/opt/llvm/bin/clang++ \
73+
-DCMAKE_CXX_FLAGS="-stdlib=libc++" \
74+
-DCMAKE_INSTALL_PREFIX=/opt/antlr4 \
75+
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
76+
-DANTLR4_INSTALL=ON
77+
cmake --build build -j$(nproc)
78+
cmake --install build
79+
```
80+
81+
Then pass the install prefix when configuring ATS:
82+
```bash
83+
cmake -B build -DCMAKE_PREFIX_PATH=/opt/antlr4 ...
84+
```
85+
86+
If the `antlr4` tool is not on `PATH`, set it explicitly:
87+
```bash
88+
cmake -B build -DANTLR4_EXECUTABLE=/opt/antlr4/bin/antlr4 ...
89+
```
90+
2891
## Development Setup
2992

3093
### 1. Clone and Setup Environment

0 commit comments

Comments
 (0)