v2.8.5.rc1 didn't work perfectly for Nokogiri (see https://github.com/sparklemotion/nokogiri/pull/2974). Specifically: if a system library like libxml2.so is installed in a default search path (e.g., this is the case for some system installations of ruby), then the linker dynamically links against the system library rather than statically linking against the packaged static archive.
the implementation
This PR is an attempt to fix that by asking the developer to pass in the name of the static archive when choosing to statically link. For example:
rewrite the linker flags to ensure we link against the packaged static archive
remove all -L and -l flags
inject the full path to the static archive, e.g. /path/to/foopkg/1.1.1/lib/libfoo.a
remember what static archives it's already seen, so any subsequent pkg-config packages that reference earlier packages in a Requires section will also have their flags resolved correctly.
This PR also makes sure to prepend to $libs instead of appending to it. (Since it now contains archive file paths, this seems like a sensible thing to do.) Finally, this also conditionally adds --static to the pkg-config flags only when a static build is requested with the static: kwarg to mkmf_config.
a note on the new parameter
It may be worth noting why we ask the developer to pass in the name of the static archive root (e.g., xml2 above). While it seems possible to infer the name of this file from the output of pkg-config, there's so much freedom in how packages can describe themselves in a pkg-config file that my confidence is low that we could handle all possible edge cases.
Just as an example, here's the libxml2 config file for a vanilla x86-64 linux system:
the name of the file, libxml-2.0.pc doesn't match the archive name
the name of the package, libXML, doesn't match the archive name
The only place we can see the string we want, "xml2", is in the Libs section, however it's possible for multiple -l options to appear on this line, and pkg-config will emit dependencies' libraries as well when asking for --libs-only-l.
It seems best for the developer to just tell us that the libflag is -lxml2 and the static archive is libxml2.a by passing in static: "xml2".
the problem being addressed
v2.8.5.rc1 didn't work perfectly for Nokogiri (see https://github.com/sparklemotion/nokogiri/pull/2974). Specifically: if a system library like
libxml2.so
is installed in a default search path (e.g., this is the case for some system installations of ruby), then the linker dynamically links against the system library rather than statically linking against the packaged static archive.the implementation
This PR is an attempt to fix that by asking the developer to pass in the name of the static archive when choosing to statically link. For example:
In this case, MiniPortile will now:
-L
and-l
flags/path/to/foopkg/1.1.1/lib/libfoo.a
Requires
section will also have their flags resolved correctly.This PR also makes sure to prepend to
$libs
instead of appending to it. (Since it now contains archive file paths, this seems like a sensible thing to do.) Finally, this also conditionally adds--static
to thepkg-config
flags only when a static build is requested with thestatic:
kwarg tomkmf_config
.a note on the new parameter
It may be worth noting why we ask the developer to pass in the name of the static archive root (e.g.,
xml2
above). While it seems possible to infer the name of this file from the output of pkg-config, there's so much freedom in how packages can describe themselves in a pkg-config file that my confidence is low that we could handle all possible edge cases.Just as an example, here's the libxml2 config file for a vanilla x86-64 linux system:
A couple of notable things from this example:
libxml-2.0.pc
doesn't match the archive namelibXML
, doesn't match the archive nameThe only place we can see the string we want,
"xml2"
, is in theLibs
section, however it's possible for multiple-l
options to appear on this line, and pkg-config will emit dependencies' libraries as well when asking for--libs-only-l
.It seems best for the developer to just tell us that the libflag is
-lxml2
and the static archive islibxml2.a
by passing instatic: "xml2"
.