Skip to content

Conversation

@otegami
Copy link
Contributor

@otegami otegami commented Dec 1, 2025

When multiple packages have the same -D or -W flags, pkgconf removes previous occurrences and keeps only the last one (merge back).
This prevents flag duplication like "-DNOMINMAX"
appearing many times.

$ pkgconf --cflags re2
-pthread -DNOMINMAX
$ ruby -r pkg-config -e 'puts PKGConfig.cflags("re2")'
-pthread -DNOMINMAX -DNOMINMAX -DNOMINMAX ...

Flags excluded from merge back (kept as duplicates):

  • -Wa, (assembler options)
  • -Wl, (linker options)
  • -Wp, (preprocessor options)

This PR only supports merge back for -D and -W flags. Other flags that pkgconf also merges back are not yet supported.

When multiple packages have the same -D or -W flags, pkgconf
removes previous occurrences and keeps only the last one
(mergeback).
This prevents flag duplication like "-DNOMINMAX"
appearing many times.

```console$ pkgconf --cflags re2
-pthread -DNOMINMAX
$ ruby -r pkg-config -e 'puts PKGConfig.cflags("re2")'
-pthread -DNOMINMAX -DNOMINMAX -DNOMINMAX ...
```

Flags excluded from mergeback (kept as duplicates):
- -Wa, (assembler options)
- -Wl, (linker options)
- -Wp, (preprocessor options)

This PR only supports mergeback for -D and -W flags.
Other flags that pkgconf also mergebacks are not yet
supported.
normalized_cflags
end

def mergeback_flags(flags)
Copy link
Member

Choose a reason for hiding this comment

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

Could you add a comment that we want to implement pkgconf's pkgconf_fragment_copy() compatible behavior here?

https://github.com/pkgconf/pkgconf/blob/pkgconf-2.5.1/libpkgconf/fragment.c#L381-L416

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fix: 19cd8b8

mergebacked_flags = []
flags.each do |flag|
if mergeable_flag?(flag)
mergebacked_flags.delete(flag)
Copy link
Member

Choose a reason for hiding this comment

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

Could you add a comment that this may be slow because this checks mergebacked_flags N (the number of mergeable flags) times?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fix: de47ab7

flag.gsub(/\A-I/, "/I")
end
end
other_flags = mergeback_flags(other_flags)
Copy link
Member

Choose a reason for hiding this comment

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

Could you use merge_back not mergeback?

Could you use cflags not flags? We only support C flags for now, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fix: c6b9da8

end
end

sub_test_case("cflags mergeback") do
Copy link
Member

Choose a reason for hiding this comment

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

Can we simplify this?

sub_test_case("#merge_back_cflags") do
  def merge_back_cflags(cflags)
    @glib.__send__(:merge_back_cflags, cflags)
  end

  def test_define
    assert_equal("-I/main -I/dep -DFOO",
               merge_back_cflags("-I/main -DFOO -I/dep -DFOO"))
  end
end

See also:

sub_test_case("#parse_requires") do
def parse_requires(requires)
@glib.__send__(:parse_requires, requires)
end
def test_broken_version
assert_equal(["fribidi"],
parse_requires("fribidi >= fribidi_required_dep"))
end
def test_greater_than_or_equals_to
assert_equal(["fribidi"],
parse_requires("fribidi >= 1.0"))
end
def test_greater_than
assert_equal(["fribidi"],
parse_requires("fribidi > 1.0"))
end
def test_less_than_or_equals_to
assert_equal(["fribidi"],
parse_requires("fribidi <= 1.0"))
end
def test_less_than
assert_equal(["fribidi"],
parse_requires("fribidi < 1.0"))
end
def test_equals_to
assert_equal(["fribidi"],
parse_requires("fribidi = 1.0"))
end
end

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fix: 062f4be

@otegami
Copy link
Contributor Author

otegami commented Dec 1, 2025

Thank you for reviews. I've just addressed all of review comments, so far.

@otegami otegami requested a review from kou December 1, 2025 07:11
end
all_cflags = normalize_cflags(Shellwords.split(cflags_set.join(" ")))
path_flags, other_flags = all_cflags.partition {|flag| /\A-I/ =~ flag}
path_flags, cflags = all_cflags.partition {|flag| /\A-I/ =~ flag}
Copy link
Member

Choose a reason for hiding this comment

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

We can keep other_flags because -I is also C flags and this method is collect_cflags.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fix: 5230529 Sure.

It's because this method collect cflags, so all of
them are cflags too.
Comment on lines 587 to 588
# NOTE: This may be slow because this checks merge_back_cflags N times (where
# N is the number of mergeable flags).
Copy link
Member

Choose a reason for hiding this comment

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

Could you move this to just before mergebacked_cflags.delete(cflag)?
The code may be slow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fix: b9a7cdc

# NOTE: This may be slow because this checks merge_back_cflags N times (where
# N is the number of mergeable flags).
def merge_back_cflags(cflags)
mergebacked_cflags = []
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
mergebacked_cflags = []
merge_backed_cflags = []

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fix: 6e7d245

"-Wa,--noexecstack", "-Wl,--as-needed", "-Wp,-DFOO"]))
end

def test_mixed_flags
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def test_mixed_flags
def test_mixed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fix: c21530f

@otegami
Copy link
Contributor Author

otegami commented Dec 1, 2025

Thank you for reviews. I've just addressed all of review comments, so far.

@otegami otegami requested a review from kou December 1, 2025 07:36
@kou
Copy link
Member

kou commented Dec 1, 2025

Update the PR description before I merge this.

@kou kou merged commit 7caeccc into ruby-gnome:main Dec 1, 2025
21 checks passed
@otegami otegami deleted the mergeback-d-and-w-flags branch December 1, 2025 07:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants