Skip to content

Commit

Permalink
Build libgumbo via autotools and rebuild on source changes
Browse files Browse the repository at this point in the history
- Implement a minimal autotools build for libgumbo.
- Make `rake gumbo:test` use the same libgumbo.a used to build the
  nokogiri extension.
- Make changes to `gumbo-parser/src` trigger a rebuild of libgumbo.
  • Loading branch information
stevecheckoway authored and flavorjones committed Jun 7, 2024
1 parent f306126 commit 3c85081
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 102 deletions.
60 changes: 13 additions & 47 deletions ext/nokogiri/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1056,54 +1056,8 @@ def configure
find_header("nokogiri_gumbo.h") || abort("nokogiri_gumbo.h not found")
else
libgumbo_recipe = process_recipe("libgumbo", "1.0.0-nokogiri", static_p, cross_build_p, false) do |recipe|
recipe.configure_options = []

class << recipe
def downloaded?
true
end

def extract
target = File.join(tmp_path, "gumbo-parser")
output("Copying gumbo-parser files into #{target}...")
FileUtils.mkdir_p(target)
FileUtils.cp(Dir.glob(File.join(PACKAGE_ROOT_DIR, "gumbo-parser/src/*")), target)
end

def configured?
true
end

def install
lib_dir = File.join(port_path, "lib")
inc_dir = File.join(port_path, "include")
FileUtils.mkdir_p([lib_dir, inc_dir])
FileUtils.cp(File.join(work_path, "libgumbo.a"), lib_dir)
FileUtils.cp(Dir.glob(File.join(work_path, "*.h")), inc_dir)
end

def compile
cflags = concat_flags(ENV["CFLAGS"], "-fPIC", "-O2", "-g")

env = { "CC" => gcc_cmd, "CFLAGS" => cflags }
if config_cross_build?
if host.include?("darwin")
env["AR"] = "#{host}-libtool"
env["ARFLAGS"] = "-o"
else
env["AR"] = "#{host}-ar"
end
env["RANLIB"] = "#{host}-ranlib"
end

execute("compile", make_cmd, { env: env })
end
end
recipe.source_directory = File.join(PACKAGE_ROOT_DIR, "gumbo-parser")
end
append_cppflags("-I#{File.join(libgumbo_recipe.path, "include")}")
$libs = $libs + " " + File.join(libgumbo_recipe.path, "lib", "libgumbo.a")
$LIBPATH = $LIBPATH | [File.join(libgumbo_recipe.path, "lib")]
ensure_func("gumbo_parse_with_options", "nokogiri_gumbo.h")
end

have_func("xmlHasFeature") || abort("xmlHasFeature() is missing.") # introduced in libxml 2.6.21
Expand Down Expand Up @@ -1142,11 +1096,23 @@ def compile
File.open("Makefile", "at") do |mk|
mk.print(<<~EOF)
.PHONY: clean-ports
all: clean-ports
clean-ports: $(DLLIB)
\t-$(Q)$(RUBY) $(srcdir)/extconf.rb --clean --#{static_p ? "enable" : "disable"}-static
EOF
end
File.open("Makefile", "at") do |mk|
mk.print(<<~EOF)
.PHONY: rebuild-libgumbo
$(TARGET_SO): rebuild-libgumbo
rebuild-libgumbo:
\t-$(Q)$(MAKE) -C tmp/#{libgumbo_recipe.host}/ports/libgumbo/1.0.0-nokogiri/libgumbo-1.0.0-nokogiri install
EOF
end

end

# rubocop:enable Style/GlobalVars
15 changes: 10 additions & 5 deletions gumbo-parser/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
build
googletest
src/*.o
fuzzer/build
src/libgumbo.a
/build
/googletest
/src/*.o
/fuzzer/build
/src/libgumbo.a
/aclocal.m4
/autom4te.cache/
/configure
/configure.in
Makefile.in
5 changes: 5 additions & 0 deletions gumbo-parser/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
if HAS_TESTS
SUBDIRS = src test
else
SUBDIRS = src
endif
File renamed without changes.
4 changes: 4 additions & 0 deletions gumbo-parser/build-aux/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Ignore everything in this directory except for this file.
# Credit: https://stackoverflow.com/a/932982
*
!/.gitignore
11 changes: 11 additions & 0 deletions gumbo-parser/configure.ac
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
AC_INIT([Gumbo], [1.0])
AC_CONFIG_SRCDIR([src/nokogiri_gumbo.h])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([subdir-objects foreign serial-tests no-dist no-installinfo no-installman -Wall])
AC_PROG_RANLIB
AC_PROG_CC
AC_PROG_CXX
AM_PROG_AR
AM_CONDITIONAL([HAS_TESTS], [test -d "${srcdir}/test"])
AC_CONFIG_FILES([Makefile src/Makefile test/Makefile])
AC_OUTPUT
34 changes: 0 additions & 34 deletions gumbo-parser/src/Makefile

This file was deleted.

20 changes: 20 additions & 0 deletions gumbo-parser/src/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
lib_LIBRARIES = libgumbo.a
libgumbo_a_SOURCES = \
ascii.c \
attribute.c \
char_ref.c \
error.c \
foreign_attrs.c \
parser.c \
string_buffer.c \
string_piece.c \
svg_attrs.c \
svg_tags.c \
tag.c \
tag_lookup.c \
token_buffer.c \
tokenizer.c \
utf8.c \
util.c \
vector.c
include_HEADERS = nokogiri_gumbo.h
21 changes: 21 additions & 0 deletions gumbo-parser/test/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
check_LIBRARIES = libgtest_main.a
libgtest_main_a_SOURCES = ../googletest/src/gtest-all.cc ../googletest/src/gtest_main.cc
libgtest_main_a_CPPFLAGS = -I$(top_srcdir)/googletest/include -I$(top_srcdir)/googletest
libgtest_main_a_CXXFLAGS = -pthread

check_PROGRAMS = gumbotest
gumbotest_SOURCES = attribute.cc \
parser.cc \
string_buffer.cc \
string_piece.cc \
test_utils.cc \
token_buffer.cc \
tokenizer.cc \
utf8.cc \
vector.cc

gumbotest_LDADD = libgtest_main.a ../src/libgumbo.a
gumbotest_LDFLAGS = -pthread
gumbotest_CPPFLAGS = -I$(top_srcdir)/googletest/include -I$(top_srcdir)/src

TESTS = gumbotest
8 changes: 6 additions & 2 deletions nokogiri.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,13 @@ Gem::Specification.new do |spec|
"ext/nokogiri/xml_xpath_context.c",
"ext/nokogiri/xslt_stylesheet.c",
"gumbo-parser/CHANGES.md",
"gumbo-parser/Makefile",
"gumbo-parser/Makefile.am",
"gumbo-parser/Makefile.in",
"gumbo-parser/THANKS",
"gumbo-parser/src/Makefile",
"gumbo-parser/configure",
"gumbo-parser/configure.ac",
"gumbo-parser/src/Makefile.am",
"gumbo-parser/src/Makefile.in",
"gumbo-parser/src/README.md",
"gumbo-parser/src/ascii.c",
"gumbo-parser/src/ascii.h",
Expand Down
2 changes: 1 addition & 1 deletion rakelib/extensions.rake
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ else
end

Rake::ExtensionTask.new("nokogiri", NOKOGIRI_SPEC.dup) do |ext|
ext.source_pattern = "*.{c,cc,cpp,h}"
ext.source_pattern = "{.,../../gumbo-parser/src}/*.{c,cc,cpp,h}"
ext.gem_spec.files.reject! { |path| File.fnmatch?("**/*.{java,jar}", path, File::FNM_EXTGLOB) }

ext.lib_dir = File.join(*["lib", "nokogiri", ENV["FAT_DIR"]].compact)
Expand Down
38 changes: 25 additions & 13 deletions rakelib/gumbo.rake
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
# frozen_string_literal: true

namespace "gumbo" do
gtest_pkg = "gumbo-parser/googletest"
gtest_lib = File.join(gtest_pkg, "make/gtest_main.a")
# We want to run the gumbo test suite using exactly the same compiled gumbo-parser
# that Nokogiri uses.
#
# To that end, we first need to get the Rake ExtensionTask to run extconf.rb which will
# run the gumbo-parser's configure script. We don't want to compile the extension
# at this point, so we make `gumbo:test` depend on the Nokogiri Makefile.

file gtest_lib => gtest_pkg do
sh("make -C gumbo-parser/googletest/make gtest_main.a")
end
gtest_pkg = "gumbo-parser/googletest"
host = RbConfig::CONFIG["host_alias"].empty? ? RbConfig::CONFIG["host"] : RbConfig::CONFIG["host_alias"]
host = host.gsub("i386", "i686")
nokogiri_makefile = File.join("tmp/#{RUBY_PLATFORM}/nokogiri/#{RUBY_VERSION}/Makefile")
gumbotest_builddir = "tmp/#{RUBY_PLATFORM}/nokogiri/#{RUBY_VERSION}/tmp/#{host}/ports/libgumbo/1.0.0-nokogiri/libgumbo-1.0.0-nokogiri"
gumbotest_configure = File.absolute_path("gumbo-parser/configure")

file gtest_pkg do
sh(<<~EOF)
Expand All @@ -15,20 +22,25 @@ namespace "gumbo" do
EOF
end

desc "Run the gumbo parser test suite"
task "test" => gtest_lib do
sh("make -j2 -C gumbo-parser")
file gumbotest_configure => gtest_pkg do
sh("autoreconf", "-fiv", chdir: "gumbo-parser")
end

desc "Clean up after the gumbo parser test suite"
task "clean" do
sh("make -j2 -C gumbo-parser clean")
desc "Run the gumbo parser test suite"
task "test" => nokogiri_makefile do
sh("make", "-j2", "-C", gumbotest_builddir, "check")
end

# Make sure the libgumbo configure script is created before trying to compile the extension.
file nokogiri_makefile => gumbotest_configure

CLOBBER.add(gtest_pkg)
CLOBBER.add(gumbotest_configure)
CLOBBER.add("gumbo-parser/Makefile.in")
CLOBBER.add("gumbo-parser/configure")
CLOBBER.add("gumbo-parser/src/Makefile.in")
CLOBBER.add("gumbo-parser/test/Makefile.in")
end

desc "Run the gumbo parser test suite"
task "gumbo" => "gumbo:test"

task "clean" => "gumbo:clean" # rubocop:disable Rake/Desc

0 comments on commit 3c85081

Please sign in to comment.