Skip to content

Commit

Permalink
Re-implement parts of mkmf_config
Browse files Browse the repository at this point in the history
As MiniPortile2's mkmf_config doesn't quite work for our use case yet,
refactor to combine its approach with our previous one: stop using
MiniPortile#activate to populate the required compiler and linker
options and instead set them ourselves based on the output of
pkg-config.

The key things we're trying to replace are as follows:

* Populating $CPPFLAGS and $LIBPATH with dir_config
* Populating $libs, $INCFLAGS, $LDFLAGS, $CFLAGS and $CXXFLAGS with
  pkg_config

Instead, we only set the following:

* $LIBPATH with the paths reported by pkg-config --libs-only-L
* $libs with all libraries, replacing them with static absolute paths
  where possible
* $INCFLAGS as reported by pkg-config --cflags-only-I
* $CFLAGS and $CXXFLAGS as reported by pkg-config --cflags-only-other
  • Loading branch information
mudge committed Mar 23, 2024
1 parent 2f66a1d commit 6ddb2cb
Showing 1 changed file with 55 additions and 9 deletions.
64 changes: 55 additions & 9 deletions ext/re2/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,30 +99,60 @@ def build_with_vendored_libraries

abseil_recipe, re2_recipe = load_recipes

# Compile Abseil
process_recipe(abseil_recipe) do |recipe|
recipe.configure_options += ['-DABSL_PROPAGATE_CXX_STD=ON', '-DCMAKE_CXX_VISIBILITY_PRESET=hidden']
# Workaround for https://github.com/abseil/abseil-cpp/issues/1510
recipe.configure_options += ['-DCMAKE_CXX_FLAGS=-DABSL_FORCE_WAITER_MODE=4'] if windows?
end

abseil_recipe.activate

# Compile RE2
process_recipe(re2_recipe) do |recipe|
# Specify Abseil's path so RE2 will prefer that over any system Abseil
recipe.configure_options += ["-DCMAKE_PREFIX_PATH=#{abseil_recipe.path}", '-DCMAKE_CXX_FLAGS=-DNDEBUG',
'-DCMAKE_CXX_VISIBILITY_PRESET=hidden']
end

dir_config("re2", File.join(re2_recipe.path, 'include'), File.join(re2_recipe.path, 'lib'))
dir_config("abseil", File.join(abseil_recipe.path, 'include'), File.join(abseil_recipe.path, 'lib'))
# on macOS, pkg-config will not return --cflags without this
ENV["PKG_CONFIG_ALLOW_SYSTEM_CFLAGS"] = "t"

pkg_config_paths = [
"#{abseil_recipe.path}/lib/pkgconfig",
"#{re2_recipe.path}/lib/pkgconfig"
"#{abseil_recipe.lib_path}/pkgconfig",
"#{re2_recipe.lib_path}/pkgconfig"
]
pkg_config_paths.prepend(ENV['PKG_CONFIG_PATH']) if ENV['PKG_CONFIG_PATH']
ENV['PKG_CONFIG_PATH'] = pkg_config_paths.join(File::PATH_SEPARATOR)

re2_recipe.mkmf_config(pkg: 're2', static: 're2')
pc_file = File.join(re2_recipe.lib_path, 'pkgconfig', 're2.pc')

static_library_dirs = minimal_pkg_config(pkg_config_paths, pc_file, '--libs-only-L', '--static')
.shellsplit
.map { |flag| flag.sub(/\A-L/, "") }

$LIBPATH = static_library_dirs | $LIBPATH

# Replace all -l flags that can be found in one of the static library
# directories with the full path instead.
libflags = minimal_pkg_config(pkg_config_paths, pc_file, '--libs-only-l', '--static')
.shellsplit
.map do |flag|
next flag unless flag.start_with?("-l")

static_lib = "lib#{flag[2..]}.#{$LIBEXT}"
static_lib_dir = static_library_dirs.find { |dir| File.exist?(File.join(dir, static_lib)) }
next flag unless static_lib_dir

File.join(static_lib_dir, static_lib)
end

$libs = [libflags, $libs].join(" ").strip

# Prepend INCFLAGS
incflags = minimal_pkg_config(pkg_config_paths, pc_file, '--cflags-only-I')
$INCFLAGS = [incflags, $INCFLAGS].join(" ").strip

# Append CFLAGS and CXXFLAGS
cflags = minimal_pkg_config(pkg_config_paths, pc_file, '--cflags-only-other')
$CFLAGS = [$CFLAGS, cflags].join(" ").strip
$CXXFLAGS = [$CXXFLAGS, cflags].join(" ").strip
end

def build_extension
Expand Down Expand Up @@ -251,6 +281,22 @@ def process_recipe(recipe)
end
end

def minimal_pkg_config(paths, pc_file, *options)
if ($PKGCONFIG ||=
(pkgconfig = MakeMakefile.with_config("pkg-config") {MakeMakefile.config_string("PKG_CONFIG") || "pkg-config"}) &&
MakeMakefile.find_executable0(pkgconfig) && pkgconfig)
pkgconfig = $PKGCONFIG
else
raise RuntimeError, "pkg-config is not found"
end

envs = ["PKG_CONFIG_PATH" => [*paths, ENV["PKG_CONFIG_PATH"]].compact.join(File::PATH_SEPARATOR)]
response = xpopen([*envs, pkgconfig, *options, pc_file], err: %i[child out], &:read)
raise RuntimeError, response unless $?.success?

response.strip
end

def config_system_libraries?
enable_config("system-libraries", ENV.key?('RE2_USE_SYSTEM_LIBRARIES'))
end
Expand Down

0 comments on commit 6ddb2cb

Please sign in to comment.