Top Level Namespace

Defined Under Namespace

Modules: CurlImpersonate

Instance Method Summary collapse

Instance Method Details

#configure_from_dir(dir) ⇒ Object

Resolve libcurl-impersonate location.

Priority:

1. ENV["CURL_IMPERSONATE_DIR"]                     — explicit override (CI)
2. ext/curl_impersonate/vendor/<arch>/             — bundled in precompiled gem
3. pkg-config --libs --cflags libcurl-impersonate  — system install (brew/apt)

In all cases we end up statically linking libcurl-impersonate.a so that the resulting .bundle / .so has BoringSSL baked in and the end user does not need the library installed at runtime.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'ext/curl_impersonate/extconf.rb', line 32

def configure_from_dir(dir)
  raise "CURL_IMPERSONATE_DIR=#{dir} does not exist" unless File.directory?(dir)

  lib_dir = File.join(dir, "lib")
  include_dir = File.join(dir, "include")

  $LIBPATH.unshift(lib_dir) if File.directory?(lib_dir)
  $CFLAGS << " -I#{include_dir.shellescape}" if File.directory?(include_dir)
  $CFLAGS << " -I#{File.join(include_dir, "curl-impersonate").shellescape}" if File.directory?(File.join(include_dir, "curl-impersonate"))

  static_archive = File.join(lib_dir, "libcurl-impersonate.a")
  unless File.exist?(static_archive)
    raise "libcurl-impersonate.a not found under #{lib_dir}"
  end

  # Link the static archive directly so its symbols (including curl_easy_impersonate)
  # end up in our .bundle / .so.
  $LDFLAGS << " #{static_archive.shellescape}"

  # libcurl-impersonate.a bundles BoringSSL, nghttp{2,3}, ngtcp2, zstd, and
  # brotli statically — but its remaining external dependencies have to be
  # linked separately. The list differs by target platform; we use the
  # vendor directory name as a hint when one is available, otherwise fall
  # back to RUBY_PLATFORM.
  target = File.basename(dir)
  target = RUBY_PLATFORM if target.empty? || target == "vendor"

  case target
  when /darwin/
    # Source: pkg-config --libs libcurl-impersonate on brew installation.
    $LDFLAGS << " -framework CoreFoundation -framework SystemConfiguration"
    $LDFLAGS << " -framework Security -framework LDAP"
    # ruby/setup-ruby on macos-14 builds a Ruby whose libruby has an absolute
    # install_name (e.g. /Users/runner/hostedtoolcache/Ruby/3.3.11/arm64/lib/
    # libruby.3.3.dylib). Any extension we statically-link against that Ruby
    # inherits the absolute reference, breaking the precompiled gem on every
    # other machine. Tell the linker to leave Ruby symbols unresolved and let
    # the dynamic loader fill them in at require time — this is the standard
    # macOS pattern for portable Ruby extensions.
    $DLDFLAGS << " -Wl,-undefined,dynamic_lookup"
    $libs    = "#{$libs} -lresolv -liconv -lz -lc++"
  when /linux/
    # The lexiforest release tarball is a fully-static archive — zstd, brotli,
    # idn2, nghttp{2,3}, ngtcp2, BoringSSL, and a copy of curl itself are all
    # statically linked into libcurl-impersonate.a. The only external symbols
    # are the system C/C++ runtime, zlib (often satisfied by libz.so.1 which
    # ships on every distro), and a handful of pthread/dl/m intrinsics.
    $libs    = "#{$libs} -lz -lpthread -ldl -lm -lstdc++"
  end
end

#configure_from_pkg_configObject



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'ext/curl_impersonate/extconf.rb', line 83

def configure_from_pkg_config
  unless pkg_config("libcurl-impersonate")
    raise "pkg-config could not locate libcurl-impersonate"
  end

  # pkg_config sets $LIBS to "-lcurl-impersonate -lz ...". We want the static .a
  # baked into the .bundle, so prepend the absolute path to the archive and strip
  # the dynamic -lcurl-impersonate flag.
  libdir = `pkg-config --variable=libdir libcurl-impersonate`.strip
  static_archive = File.join(libdir, "libcurl-impersonate.a")
  unless File.exist?(static_archive)
    raise "libcurl-impersonate.a not found at #{static_archive}"
  end

  $libs = $libs.to_s.gsub(/-lcurl-impersonate\b/, "").strip
  $LDFLAGS << " #{static_archive.shellescape}"
end