Skip to content

Commit 184a2f9

Browse files
committed
feat: unify CPPFLAGS and CXXFLAGS by default
CPPFLAGS and CXXFLAGS are merged into a single deduplicated value after parsing, both in apptools and magicflags. Use --separate-flags-CPP-CXX to opt out of unification. Fixes #4
1 parent 3b91f4e commit 184a2f9

4 files changed

Lines changed: 140 additions & 0 deletions

File tree

src/compiletools/apptools.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,13 @@ def add_common_arguments(cap, argv=None, variant=None):
170170
action="append",
171171
default=[],
172172
)
173+
compiletools.utils.add_flag_argument(
174+
parser=cap,
175+
name="separate-flags-CPP-CXX",
176+
dest="separate_flags_CPP_CXX",
177+
default=False,
178+
help="Keep CPPFLAGS and CXXFLAGS separate instead of unified.",
179+
)
173180
compiletools.git_utils.NameAdjuster.add_arguments(cap)
174181
_add_xxpend_arguments(cap, xxpendableargs=("include", "cppflags", "cflags", "cxxflags"))
175182
add_locking_arguments(cap)
@@ -944,6 +951,22 @@ def _do_xxpend(args, name):
944951
setattr(args, name, attr)
945952

946953

954+
def _unify_cpp_cxx_flags(args):
955+
"""Combine CPPFLAGS and CXXFLAGS into a single deduplicated value.
956+
957+
Skipped when --separate-flags-CPP-CXX is set.
958+
"""
959+
if getattr(args, 'separate_flags_CPP_CXX', False):
960+
return
961+
unified = " ".join(
962+
compiletools.utils.combine_and_deduplicate_compiler_flags(
963+
args.CPPFLAGS, args.CXXFLAGS
964+
)
965+
)
966+
args.CPPFLAGS = unified
967+
args.CXXFLAGS = unified
968+
969+
947970
def _deduplicate_all_flags(args):
948971
"""Deduplicate all compiler and linker flags after all processing is complete"""
949972
flaglist = ("CPPFLAGS", "CFLAGS", "CXXFLAGS", "LDFLAGS")
@@ -1071,6 +1094,7 @@ def _commonsubstitutions(args):
10711094
_add_include_paths_to_flags(args)
10721095
_add_flags_from_pkg_config(args)
10731096
_set_project_version(args)
1097+
_unify_cpp_cxx_flags(args)
10741098

10751099
try:
10761100
# If the user didn't explicitly supply a bindir then modify the bindir to use the variant name

src/compiletools/magicflags.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,15 @@ def _parse(self, filename):
343343
flagsforfilename[sz.Str("LDFLAGS")].extend(flagsforfilename[sz.Str("LINKFLAGS")])
344344
del flagsforfilename[sz.Str("LINKFLAGS")]
345345

346+
# Unify CPPFLAGS and CXXFLAGS in magic flags (unless opted out)
347+
if not getattr(self._args, 'separate_flags_CPP_CXX', False):
348+
cpp_key = sz.Str("CPPFLAGS")
349+
cxx_key = sz.Str("CXXFLAGS")
350+
if cpp_key in flagsforfilename or cxx_key in flagsforfilename:
351+
combined = flagsforfilename[cpp_key] + flagsforfilename[cxx_key]
352+
flagsforfilename[cpp_key] = list(combined)
353+
flagsforfilename[cxx_key] = list(combined)
354+
346355
# Deduplicate all flags while preserving order, with smart compiler flag handling
347356
for key in flagsforfilename:
348357
flagsforfilename[key] = compiletools.utils.deduplicate_compiler_flags(flagsforfilename[key])

src/compiletools/test_apptools.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,3 +333,63 @@ def test_user_config_append_cxxflags(self):
333333
# print(args)
334334
# Check that the append-CXXFLAGS argument made its way into the CXXFLAGS
335335
assert "-fdiagnostics-color=always" in args.CXXFLAGS
336+
337+
338+
class TestUnifyCppCxxFlags:
339+
"""Tests for CPPFLAGS/CXXFLAGS unification (default behavior)."""
340+
341+
def setup_method(self):
342+
uth.reset()
343+
344+
def _parse(self, extra_argv=None):
345+
"""Parse args with a temp config and optional extra argv."""
346+
with uth.TempDirContext():
347+
uth.create_temp_ct_conf(os.getcwd())
348+
cfgfile = "foo.dbg.conf"
349+
uth.create_temp_config(os.getcwd(), cfgfile)
350+
argv = ["--config=" + cfgfile, "-v"]
351+
if extra_argv:
352+
argv.extend(extra_argv)
353+
cap = configargparse.getArgumentParser(
354+
description="Test unify CPP/CXX flags",
355+
formatter_class=configargparse.ArgumentDefaultsHelpFormatter,
356+
auto_env_var_prefix="",
357+
default_config_files=["ct.conf"],
358+
args_for_setting_config_path=["-c", "--config"],
359+
ignore_unknown_config_file_keys=True,
360+
)
361+
compiletools.apptools.add_common_arguments(cap)
362+
compiletools.apptools.add_link_arguments(cap)
363+
return compiletools.apptools.parseargs(cap, argv)
364+
365+
def test_unified_by_default(self):
366+
"""After parseargs, CPPFLAGS and CXXFLAGS are identical."""
367+
args = self._parse()
368+
assert args.CPPFLAGS == args.CXXFLAGS
369+
370+
def test_unified_with_both_specified(self):
371+
"""When both flags are given, both end up containing both values."""
372+
args = self._parse(["--CPPFLAGS=-DFOO", "--CXXFLAGS=-DBAR"])
373+
assert "-DFOO" in args.CPPFLAGS
374+
assert "-DBAR" in args.CPPFLAGS
375+
assert "-DFOO" in args.CXXFLAGS
376+
assert "-DBAR" in args.CXXFLAGS
377+
assert args.CPPFLAGS == args.CXXFLAGS
378+
379+
def test_separate_mode_allows_divergence(self):
380+
"""--separate-flags-CPP-CXX keeps them independent."""
381+
args = self._parse([
382+
"--CPPFLAGS=-DFOO",
383+
"--CXXFLAGS=-DBAR",
384+
"--separate-flags-CPP-CXX",
385+
])
386+
assert "-DFOO" in args.CPPFLAGS
387+
assert "-DBAR" not in args.CPPFLAGS
388+
assert "-DBAR" in args.CXXFLAGS
389+
assert "-DFOO" not in args.CXXFLAGS
390+
391+
def test_append_cppflags_appears_in_both(self):
392+
"""--append-cppflags value appears in both CPPFLAGS and CXXFLAGS."""
393+
args = self._parse(["--append-CPPFLAGS=-DAPPENDED"])
394+
assert "-DAPPENDED" in args.CPPFLAGS
395+
assert "-DAPPENDED" in args.CXXFLAGS

src/compiletools/test_magicflags.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,3 +809,50 @@ def test_magic_flags_macro_state_equivalence(self, pkgconfig_env):
809809
+ "\n".join(f" {name}: Direct={dv}, Cpp={cv}" for name, dv, cv in mismatches[:10])
810810
)
811811

812+
def test_magic_cppflags_unified_with_cxxflags(self):
813+
"""Magic CPPFLAGS appear in CXXFLAGS (and vice versa) when unified."""
814+
files = uth.write_sources({
815+
"test_unified.cpp": '//#CPPFLAGS=-DFROMCPP\nint main() { return 0; }\n',
816+
})
817+
source_file = str(files["test_unified.cpp"])
818+
819+
mf = tb.create_magic_parser(["--magic=direct"], tempdir=self._tmpdir)
820+
result = mf.parse(source_file)
821+
822+
cpp_flags = [str(f) for f in result.get(sz.Str("CPPFLAGS"), [])]
823+
cxx_flags = [str(f) for f in result.get(sz.Str("CXXFLAGS"), [])]
824+
assert "-DFROMCPP" in cpp_flags, f"Expected -DFROMCPP in CPPFLAGS, got {cpp_flags}"
825+
assert "-DFROMCPP" in cxx_flags, f"Expected -DFROMCPP in CXXFLAGS, got {cxx_flags}"
826+
827+
def test_magic_cxxflags_unified_with_cppflags(self):
828+
"""Magic CXXFLAGS appear in CPPFLAGS when unified."""
829+
files = uth.write_sources({
830+
"test_unified2.cpp": '//#CXXFLAGS=-DFROMCXX\nint main() { return 0; }\n',
831+
})
832+
source_file = str(files["test_unified2.cpp"])
833+
834+
mf = tb.create_magic_parser(["--magic=direct"], tempdir=self._tmpdir)
835+
result = mf.parse(source_file)
836+
837+
cpp_flags = [str(f) for f in result.get(sz.Str("CPPFLAGS"), [])]
838+
cxx_flags = [str(f) for f in result.get(sz.Str("CXXFLAGS"), [])]
839+
assert "-DFROMCXX" in cpp_flags, f"Expected -DFROMCXX in CPPFLAGS, got {cpp_flags}"
840+
assert "-DFROMCXX" in cxx_flags, f"Expected -DFROMCXX in CXXFLAGS, got {cxx_flags}"
841+
842+
def test_magic_flags_separate_mode(self):
843+
"""Magic CPPFLAGS stay separate from CXXFLAGS with --separate-flags-CPP-CXX."""
844+
files = uth.write_sources({
845+
"test_separate.cpp": '//#CPPFLAGS=-DFROMCPP\n//#CXXFLAGS=-DFROMCXX\nint main() { return 0; }\n',
846+
})
847+
source_file = str(files["test_separate.cpp"])
848+
849+
mf = tb.create_magic_parser(["--magic=direct", "--separate-flags-CPP-CXX"], tempdir=self._tmpdir)
850+
result = mf.parse(source_file)
851+
852+
cpp_flags = [str(f) for f in result.get(sz.Str("CPPFLAGS"), [])]
853+
cxx_flags = [str(f) for f in result.get(sz.Str("CXXFLAGS"), [])]
854+
assert "-DFROMCPP" in cpp_flags
855+
assert "-DFROMCXX" not in cpp_flags, f"CPPFLAGS should not contain -DFROMCXX in separate mode, got {cpp_flags}"
856+
assert "-DFROMCXX" in cxx_flags
857+
assert "-DFROMCPP" not in cxx_flags, f"CXXFLAGS should not contain -DFROMCPP in separate mode, got {cxx_flags}"
858+

0 commit comments

Comments
 (0)