From 5883d8aaed87c344a371a7dc95abab92e0e599b5 Mon Sep 17 00:00:00 2001 From: otegami Date: Thu, 27 Nov 2025 15:32:19 +0900 Subject: [PATCH 1/3] Use Requires.private only for static linking GitHub: - https://github.com/ruby-gnome/pkg-config/pull/41#issuecomment-3584170525 - https://github.com/ruby-gnome/pkg-config/pull/41#issuecomment-3584271174 By default, exclude `Requires.private` dependencies from cflags and libs output to match pkgconf's behavior. When the new `static: true` option is specified, include `Requires.private` dependencies for static linking scenarios. This change makes the default behavior consistent with pkgconf while still supporting static linking use-cases through an explicit option. Co-Authored-By: kou --- lib/pkg-config.rb | 91 +++++++++++++++++++++++------------------ test/test-pkg-config.rb | 81 ++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 39 deletions(-) diff --git a/lib/pkg-config.rb b/lib/pkg-config.rb index 197af8b..0f1368d 100644 --- a/lib/pkg-config.rb +++ b/lib/pkg-config.rb @@ -37,56 +37,58 @@ def msvc? /mswin/.match(RUBY_PLATFORM) and /^cl\b/.match(RbConfig::CONFIG["CC"]) end - def package_config(package) + def package_config(package, **options) PackageConfig.new(package, - :msvc_syntax => msvc?, - :override_variables => @@override_variables, - :paths => @@paths) + { + msvc_syntax: msvc?, + override_variables: @@override_variables, + paths: @@paths, + }.merge(options)) end - def exist?(pkg) - package_config(pkg).exist? + def exist?(pkg, **options) + package_config(pkg, **options).exist? end - def libs(pkg) - package_config(pkg).libs + def libs(pkg, **options) + package_config(pkg, **options).libs end - def libs_only_l(pkg) - package_config(pkg).libs_only_l + def libs_only_l(pkg, **options) + package_config(pkg, **options).libs_only_l end - def libs_only_L(pkg) - package_config(pkg).libs_only_L + def libs_only_L(pkg, **options) + package_config(pkg, **options).libs_only_L end - def cflags(pkg) - package_config(pkg).cflags + def cflags(pkg, **options) + package_config(pkg, **options).cflags end - def cflags_only_I(pkg) - package_config(pkg).cflags_only_I + def cflags_only_I(pkg, **options) + package_config(pkg, **options).cflags_only_I end - def cflags_only_other(pkg) - package_config(pkg).cflags_only_other + def cflags_only_other(pkg, **options) + package_config(pkg, **options).cflags_only_other end - def modversion(pkg) - package_config(pkg).version + def modversion(pkg, **options) + package_config(pkg, **options).version end - def description(pkg) - package_config(pkg).description + def description(pkg, **options) + package_config(pkg, **options).description end - def variable(pkg, name) - package_config(pkg).variable(name) + def variable(pkg, name, **options) + package_config(pkg, **options).variable(name) end - def check_version?(pkg, major=0, minor=0, micro=0) - return false unless exist?(pkg) - ver = modversion(pkg).split(".").collect {|item| item.to_i} + def check_version?(pkg, major=0, minor=0, micro=0, **options) + return false unless exist?(pkg, **options) + ver = modversion(pkg, **options).split(".").collect {|item| item.to_i} (0..2).each {|i| ver[i] = 0 unless ver[i]} (ver[0] > major || @@ -95,18 +97,18 @@ def check_version?(pkg, major=0, minor=0, micro=0) ver[2] >= micro)) end - def have_package(pkg, major=nil, minor=0, micro=0) + def have_package(pkg, major=nil, minor=0, micro=0, **options) message = "#{pkg}" unless major.nil? message << " version (>= #{major}.#{minor}.#{micro})" end major ||= 0 result = checking_for(checking_message(message), "%s") do - if check_version?(pkg, major, minor, micro) - "yes (#{modversion(pkg)})" + if check_version?(pkg, major, minor, micro, **options) + "yes (#{modversion(pkg, **options)})" else - if exist?(pkg) - "no (#{modversion(pkg)})" + if exist?(pkg, **options) + "no (#{modversion(pkg, **options)})" else "no (nonexistent)" end @@ -114,8 +116,8 @@ def have_package(pkg, major=nil, minor=0, micro=0) end enough_version = result.start_with?("yes") if enough_version - libraries = libs_only_l(pkg) - dldflags = libs(pkg) + libraries = libs_only_l(pkg, **options) + dldflags = libs(pkg, **options) dldflags = (Shellwords.shellwords(dldflags) - Shellwords.shellwords(libraries)) dldflags = dldflags.map {|s| /\s/ =~ s ? "\"#{s}\"" : s }.join(" ") @@ -125,11 +127,11 @@ def have_package(pkg, major=nil, minor=0, micro=0) else $LDFLAGS += " " + dldflags end - $CFLAGS += " " + cflags_only_other(pkg) + $CFLAGS += " " + cflags_only_other(pkg, **options) if defined?($CXXFLAGS) - $CXXFLAGS += " " + cflags_only_other(pkg) + $CXXFLAGS += " " + cflags_only_other(pkg, **options) end - $INCFLAGS += " " + cflags_only_I(pkg) + $INCFLAGS += " " + cflags_only_I(pkg, **options) end enough_version end @@ -408,6 +410,7 @@ def initialize(name, options={}) @paths.unshift(*(@options[:paths] || [])) @paths = normalize_paths(@paths) @msvc_syntax = @options[:msvc_syntax] + @static = @options[:static] @variables = @declarations = nil override_variables = self.class.custom_override_variables @override_variables = parse_override_variables(override_variables) @@ -528,7 +531,12 @@ def collect_requires(&block) private def collect_cflags - target_packages = [self, *all_required_packages] + target_packages = [self] + if @static + target_packages += all_required_packages + else + target_packages += required_packages + end cflags_set = [] target_packages.each do |package| cflags_set << package.declaration("Cflags") @@ -580,7 +588,12 @@ def normalize_cflags(cflags) end def collect_libs - target_packages = [*required_packages, self] + if @static + target_packages = all_required_packages + else + target_packages = required_packages + end + target_packages += [self] libs_set = [] target_packages.each do |package| libs_set << package.declaration("Libs") diff --git a/test/test-pkg-config.rb b/test/test-pkg-config.rb index eace04b..b3fe78e 100644 --- a/test/test-pkg-config.rb +++ b/test/test-pkg-config.rb @@ -1,5 +1,6 @@ require "mkmf" require "tempfile" +require "fileutils" require "pkg-config" @@ -314,4 +315,84 @@ def test_equals_to parse_requires("fribidi = 1.0")) end end + + sub_test_case("static option") do + def create_pc_file(name, content) + pc_dir = File.join(@tmpdir, "pkgconfig") + FileUtils.mkdir_p(pc_dir) + pc_path = File.join(pc_dir, "#{name}.pc") + File.write(pc_path, content) + pc_dir + end + + def setup + PackageConfig.clear_configure_args_cache + @tmpdir = Dir.mktmpdir + @pc_dir = create_pc_file("main-package", <<-PC) +prefix=/usr/local +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: main-package +Description: Main package for testing +Version: 1.0.0 +Requires: dep-package +Requires.private: private-dep-package +Libs: -L${libdir} -lmain +Cflags: -I${includedir}/main + PC + create_pc_file("dep-package", <<-PC) +prefix=/usr/local +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: dep-package +Description: Dependency package +Version: 1.0.0 +Libs: -L${libdir} -ldep +Cflags: -I${includedir}/dep + PC + create_pc_file("private-dep-package", <<-PC) +prefix=/usr/local +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: private-dep-package +Description: Private dependency package +Version: 1.0.0 +Libs: -L${libdir} -lprivate-dep +Cflags: -I${includedir}/private-dep + PC + end + + def teardown + FileUtils.rm_rf(@tmpdir) + end + + def test_cflags_without_static + package = PackageConfig.new("main-package", paths: [@pc_dir]) + assert_equal("-I/usr/local/include/main -I/usr/local/include/dep", + package.cflags) + end + + def test_cflags_with_static + package = PackageConfig.new("main-package", paths: [@pc_dir], static: true) + assert_equal("-I/usr/local/include/main " + + "-I/usr/local/include/private-dep " + + "-I/usr/local/include/dep", + package.cflags) + end + + def test_libs_without_static + package = PackageConfig.new("main-package", paths: [@pc_dir]) + assert_equal("-L/usr/local/lib -ldep -lmain", + package.libs) + end + + def test_libs_with_static + package = PackageConfig.new("main-package", paths: [@pc_dir], static: true) + assert_equal("-L/usr/local/lib -lprivate-dep -ldep -lmain", + package.libs) + end + end end From d30a139960750a8c5eb2ff9bd042eef310cec4b9 Mon Sep 17 00:00:00 2001 From: otegami Date: Thu, 27 Nov 2025 16:48:31 +0900 Subject: [PATCH 2/3] Install pkgconf --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3d3c971..56435c9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,7 +53,7 @@ jobs: if: | runner.os == 'Windows' run: | - ridk exec pacman --sync --noconfirm mingw-w64-x86_64-cairo mingw-w64-ucrt-x86_64-cairo + ridk exec pacman --sync --noconfirm mingw-w64-x86_64-cairo mingw-w64-ucrt-x86_64-cairo mingw-w64-x86_64-pkgconf mingw-w64-ucrt-x86_64-pkgconf - name: Install dependencies run: | bundle install From 183cb7bf2e99b8989226d4d05a8f97a81da80a71 Mon Sep 17 00:00:00 2001 From: otegami Date: Thu, 27 Nov 2025 16:57:59 +0900 Subject: [PATCH 3/3] debug: Add debug output for Windows pkg-config detection --- .github/workflows/test.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 56435c9..32e56a2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -57,6 +57,27 @@ jobs: - name: Install dependencies run: | bundle install + - name: Debug pkg-config (Windows) + if: | + runner.os == 'Windows' + run: | + echo "=== PATH ===" + echo $env:Path + echo "" + echo "=== which pkgconf ===" + Get-Command pkgconf -ErrorAction SilentlyContinue + echo "" + echo "=== which pkg-config ===" + Get-Command pkg-config -ErrorAction SilentlyContinue + echo "" + echo "=== ridk exec which pkgconf ===" + ridk exec which pkgconf + echo "" + echo "=== ridk exec pkgconf --version ===" + ridk exec pkgconf --version + echo "" + echo "=== ridk exec pkgconf --cflags glib-2.0 ===" + ridk exec pkgconf --cflags glib-2.0 - name: Test run: | bundle exec rake