Skip to content
This repository has been archived by the owner on Jan 15, 2025. It is now read-only.

(maint) Use packaged libxml to build nokogiri on MacOS #832

Conversation

cthorn42
Copy link
Collaborator

This PR changes the gem install command for the Nokogiri gem. Currently when building nokogiri it uses the system libxml2 and libxslt. We now will pass in an option in the gem install command to use the expected libraries.

@cthorn42 cthorn42 requested review from a team as code owners April 19, 2024 18:04
@cthorn42 cthorn42 added the blocked PRs blocked on work external to the PR itself label Apr 19, 2024
pkg.install do
"#{settings[:gem_install]} #{name}-#{version}.gem"
end
end
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a placeholder, I think the long term solution is to change this to just add to the install command something like #{pkg.gem_install_options}, where we define the pkg.gem_install_options in the nokogiri component.
I can't quite wrap my head around how to implement this yet though.

Copy link
Contributor

@joshcooper joshcooper Apr 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One option to "pass" additional options is to define something like this in _base-rubygem.rb:

pkg.install do
  if gem_install_options
    "#{settings[:gem_install]} #{name}-#{version}.gem -- #{gem_install_options}"
  else
    "#{settings[:gem_install]} #{name}-#{version}.gem"
  end
end

And then in rubygem-nokogiri.rb specify the options prior to instance_eval'ing the base component:

gem_install_options = "--use-system-libraries --with-xml2-lib=... --with-xml2-include=... etc"
instance_eval File.read('configs/components/_base-rubygem.rb')

Copy link
Collaborator Author

@cthorn42 cthorn42 Apr 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Josh, took a bit to wrap my head around things but the prior to the instance_eval was the key point. I've pushed up my changes. Working on last little bit now, vanagon-generic-job is failing osx-12-arm, which is cross compiled.

@cthorn42
Copy link
Collaborator Author

Here is my current work in progress for runtime, the otool output for the nokogiri bundle:

otool -L /opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems/nokogiri-1.14.2/lib/nokogiri/nokogiri.bundle
/opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems/nokogiri-1.14.2/lib/nokogiri/nokogiri.bundle:
	/opt/puppetlabs/puppet/lib/libruby.3.2.dylib (compatibility version 3.2.0, current version 3.2.3)
	/opt/puppetlabs/puppet/lib/libexslt.0.dylib (compatibility version 9.0.0, current version 9.21.0)
	/opt/puppetlabs/puppet/lib/libxslt.1.dylib (compatibility version 3.0.0, current version 3.39.0)
	/opt/puppetlabs/puppet/lib/libxml2.2.dylib (compatibility version 15.0.0, current version 15.6.0)
	/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.100.3)

This looks right when compared to the same output on the currenty nightly osx-13-arm64 output:

otool -L /opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems/nokogiri-1.14.2/lib/nokogiri/nokogiri.bundle
/opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems/nokogiri-1.14.2/lib/nokogiri/nokogiri.bundle:
	/opt/puppetlabs/puppet/lib/libruby.3.2.dylib (compatibility version 3.2.0, current version 3.2.3)
	/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.100.3)
	/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
	/usr/lib/liblzma.5.dylib (compatibility version 6.0.0, current version 6.3.0)

Note in my work in progress we see the libxml2 and libxslt are using the bundled libraries in my work in progress, and in comparission the current nightlies as expected does not load our bundled libraries.

Now where things look wrong is when running the Nokogiri binary, this is how it the binary looks when run from the current nightly build:

 /opt/puppetlabs/puppet/bin/nokogiri --version
# Nokogiri (1.14.2)
    ---
    warnings: []
    nokogiri:
      version: 1.14.2
      cppflags:
      - "-I/opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems/nokogiri-1.14.2/ext/nokogiri"
      - "-I/opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems/nokogiri-1.14.2/ext/nokogiri/include"
      - "-I/opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems/nokogiri-1.14.2/ext/nokogiri/include/libxml2"
      ldflags: []
    ruby:
      version: 3.2.3
      platform: arm64-darwin22
      gem_platform: arm64-darwin-22
      description: ruby 3.2.3 (2024-01-18 revision 52bb2ac0a6) [arm64-darwin22]
      engine: ruby
    libxml:
      source: packaged
      precompiled: false
      patches:
      - 0001-Remove-script-macro-support.patch
      - 0002-Update-entities-to-remove-handling-of-ssi.patch
      - 0003-libxml2.la-is-in-top_builddir.patch
      - '0009-allow-wildcard-namespaces.patch'
      libxml2_path: "/opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems/nokogiri-1.14.2/ext/nokogiri"
      memory_management: ruby
      iconv_enabled: true
      compiled: 2.10.3
      loaded: 2.10.3
    libxslt:
      source: packaged
      precompiled: false
      patches:
      - 0001-update-automake-files-for-arm64.patch
      datetime_enabled: true
      compiled: 1.1.37
      loaded: 1.1.37
    other_libraries:
      libgumbo: 1.0.0-nokogiri

Things to note in the current nightly build above, the vendored libxml is used but the system libxslt is used. The goal of this ticket is to get the libxslt to use our libxslt.
When we look at my current work in progress Nokogiri binary output we see some issues:

./puppet/bin/nokogiri --version
WARNING: Nokogiri was built against libxml version 2.9.13, but has dynamically loaded 2.12.6
# Nokogiri (1.14.2)
    ---
    warnings:
    - Nokogiri was built against libxml version 2.9.13, but has dynamically loaded 2.12.6
    nokogiri:
      version: 1.14.2
      cppflags:
      - "-I/opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems/nokogiri-1.14.2/ext/nokogiri"
      ldflags: []
    ruby:
      version: 3.2.3
      platform: arm64-darwin22
      gem_platform: arm64-darwin-22
      description: ruby 3.2.3 (2024-01-18 revision 52bb2ac0a6) [arm64-darwin22]
      engine: ruby
    libxml:
      source: system
      memory_management: ruby
      iconv_enabled: false
      compiled: 2.9.13
      loaded: 2.12.6
    libxslt:
      source: system
      datetime_enabled: true
      compiled: 1.1.39
      loaded: 1.1.39
    other_libraries:
      libgumbo: 1.0.0-nokogiri

First there is an obvious warning message about libxml, then we see that the system libxml and system libxslt are being used. That seems to be a problem.

@joshcooper
Copy link
Contributor

joshcooper commented Apr 24, 2024

I think the nightly version is correctly using the libxml2 headers that are vendored in the nokogiri gem as can be seen by this entry in cppflags:

      - "-I/opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems/nokogiri-1.14.2/ext/nokogiri/include/libxml2"

But the work is progress seems to be using compiled: 2.9.13 which is not the version in the nokogiri gem and it's not what we're using in the runtime. So I'm guessing the build is using /usr/include.

You can go full explicit mode and list the include and lib directories for each component like:

gem install nokogiri -- \
    --use-system-libraries \
    --with-xml2-lib=/path/to/builds/lib \
    --with-xml2-include=/path/to/builds/include/libxml2 \
    --with-xslt-lib=/path/to/builds/lib \
    --with-xslt-include=/path/to/builds/include

Can also use settings[:includedir] and settings[:libdir] instead of hardcoding /opt/puppetlabs/puppet/include, etc

@cthorn42
Copy link
Collaborator Author

Awesome Josh, thank you. going explicit worked:

/opt/puppetlabs/puppet/bin/nokogiri --version
# Nokogiri (1.14.2)
    ---
    warnings: []
    nokogiri:
      version: 1.14.2
      cppflags:
      - "-I/opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems/nokogiri-1.14.2/ext/nokogiri"
      ldflags: []
    ruby:
      version: 3.2.3
      platform: arm64-darwin22
      gem_platform: arm64-darwin-22
      description: ruby 3.2.3 (2024-01-18 revision 52bb2ac0a6) [arm64-darwin22]
      engine: ruby
    libxml:
      source: system
      memory_management: ruby
      iconv_enabled: true
      compiled: 2.12.6
      loaded: 2.12.6
    libxslt:
      source: system
      datetime_enabled: true
      compiled: 1.1.39
      loaded: 1.1.39
    other_libraries:
      libgumbo: 1.0.0-nokogiri
pix-arm64-macos13-6:~ root# otool -L /opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems/nokogiri-1.14.2/lib/nokogiri/nokogiri.bundle
/opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems/nokogiri-1.14.2/lib/nokogiri/nokogiri.bundle:
	/opt/puppetlabs/puppet/lib/libruby.3.2.dylib (compatibility version 3.2.0, current version 3.2.3)
	/opt/puppetlabs/puppet/lib/libexslt.0.dylib (compatibility version 9.0.0, current version 9.21.0)
	/opt/puppetlabs/puppet/lib/libxslt.1.dylib (compatibility version 3.0.0, current version 3.39.0)
	/opt/puppetlabs/puppet/lib/libxml2.2.dylib (compatibility version 15.0.0, current version 15.6.0)
	/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.100.3)

@cthorn42 cthorn42 force-pushed the maint/main/nokogiri_gem_install_patch branch 2 times, most recently from d5172ce to b7195cc Compare April 26, 2024 16:51
This PR changes the gem install command for the Nokogiri gem.
Currently when building nokogiri it uses the system libxml2 and libxslt.
We now will pass in an option in the `gem install` command to use the expected
libraries.
Also on MacOS we now set the 'pkgconfig' path as an env variable when building
Nokogiri.
@cthorn42 cthorn42 force-pushed the maint/main/nokogiri_gem_install_patch branch from b7195cc to 5f202ab Compare April 29, 2024 19:15
@cthorn42 cthorn42 removed the blocked PRs blocked on work external to the PR itself label May 1, 2024
@cthorn42
Copy link
Collaborator Author

cthorn42 commented May 1, 2024

I've removed the block label, validation for this is complete. Here is the agent-runtime-main vanagon generic job link: https://jenkins-platform.delivery.puppetlabs.net/view/vanagon-generic-builder/job/platform_vanagon-generic-builder_vanagon-packaging_generic-builder/2907/ (ignore the one failure, that is an AWS transient)
There is one issue though, the gem that gets installed is x86_64 and not arm.
So what I'm suggesting is we leave Nokogiri on MacOS support for version 11/12 ARM to be as it is; broken.
We have it fixed going forward starting with MacOS 13 and thats good enough.

@mhashizume mhashizume merged commit f9068e6 into puppetlabs-toy-chest:master May 1, 2024
3 checks passed
@joshcooper joshcooper added the bug Something isn't working label May 22, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants