@@ -218,21 +218,66 @@ parseReleaseProfile(
218218 ));
219219}
220220
221+ enum class InheritMode : uint8_t {
222+ Append,
223+ Overwrite,
224+ };
225+
226+ static Result<InheritMode>
227+ parseInheritMode (std::string_view mode) noexcept {
228+ if (mode == " append" ) {
229+ return Ok (InheritMode::Append);
230+ } else if (mode == " overwrite" ) {
231+ return Ok (InheritMode::Overwrite);
232+ } else {
233+ Bail (" invalid inherit-mode: `{}`" , mode);
234+ }
235+ }
236+
237+ static std::vector<std::string>
238+ inheritFlags (
239+ const InheritMode inheritMode, const std::vector<std::string>& baseFlags,
240+ const std::vector<std::string>& newFlags
241+ ) noexcept {
242+ if (newFlags.empty ()) {
243+ return baseFlags; // No change, use base flags.
244+ }
245+
246+ if (inheritMode == InheritMode::Append) {
247+ // Append new flags to the base flags.
248+ std::vector<std::string> merged = baseFlags;
249+ merged.insert (merged.end (), newFlags.begin (), newFlags.end ());
250+ return merged;
251+ } else {
252+ // Overwrite base flags with new flags.
253+ return newFlags;
254+ }
255+ }
256+
221257// Inherits from `dev`.
222258static Result<Profile>
223259parseTestProfile (const toml::value& val, const Profile& devProfile) noexcept {
224260 static constexpr const char * key = " test" ;
225261
226- auto cxxflags = Try (validateFlags (
227- " cxxflags" , toml::find_or<std::vector<std::string>>(
228- val, " profile" , key, " cxxflags" , devProfile.cxxflags
229- )
230- ));
231- auto ldflags = Try (validateFlags (
232- " ldflags" , toml::find_or<std::vector<std::string>>(
233- val, " profile" , key, " ldflags" , devProfile.ldflags
234- )
262+ const InheritMode inheritMode = Try (parseInheritMode (
263+ toml::find_or<std::string>(val, " profile" , key, " inherit-mode" , " append" )
235264 ));
265+ std::vector<std::string> cxxflags = inheritFlags (
266+ inheritMode, devProfile.cxxflags ,
267+ Try (validateFlags (
268+ " cxxflags" , toml::find_or_default<std::vector<std::string>>(
269+ val, " profile" , key, " cxxflags"
270+ )
271+ ))
272+ );
273+ std::vector<std::string> ldflags = inheritFlags (
274+ inheritMode, devProfile.ldflags ,
275+ Try (validateFlags (
276+ " ldflags" , toml::find_or_default<std::vector<std::string>>(
277+ val, " profile" , key, " ldflags"
278+ )
279+ ))
280+ );
236281 const auto lto =
237282 toml::find_or<bool >(val, " profile" , key, " lto" , devProfile.lto );
238283 const auto debug =
@@ -918,7 +963,7 @@ testParseProfiles() {
918963 opt-level = 1
919964
920965 [profile.test]
921- cxxflags = ["-fno-rtti"]
966+ opt-level = 3
922967 )" _toml;
923968
924969 const Profile devExpected (
@@ -932,9 +977,9 @@ testParseProfiles() {
932977 /* compDb=*/ false , /* optLevel=*/ 2 // here, the default is 3
933978 );
934979 const Profile testExpected (
935- /* cxxflags=*/ { " -fno-rtti " }, /* ldflags=*/ {}, /* lto=*/ false ,
980+ /* cxxflags=*/ {}, /* ldflags=*/ {}, /* lto=*/ false ,
936981 /* debug=*/ true ,
937- /* compDb=*/ false , /* optLevel=*/ 1
982+ /* compDb=*/ false , /* optLevel=*/ 3
938983 );
939984
940985 const auto profiles = parseProfiles (overwrite).unwrap ();
@@ -943,6 +988,70 @@ testParseProfiles() {
943988 assertEq (profiles.at (BuildProfile::Release), relExpected);
944989 assertEq (profiles.at (BuildProfile::Test), testExpected);
945990 }
991+ {
992+ const toml::value append = R"(
993+ [profile.dev]
994+ cxxflags = ["-A"]
995+
996+ [profile.test]
997+ cxxflags = ["-B"]
998+ )" _toml;
999+
1000+ const Profile devExpected (
1001+ /* cxxflags=*/ { " -A" }, /* ldflags=*/ {}, /* lto=*/ false ,
1002+ /* debug=*/ true ,
1003+ /* compDb=*/ false , /* optLevel=*/ 0
1004+ );
1005+ const Profile testExpected (
1006+ /* cxxflags=*/ { " -A" , " -B" }, /* ldflags=*/ {}, /* lto=*/ false ,
1007+ /* debug=*/ true ,
1008+ /* compDb=*/ false , /* optLevel=*/ 0
1009+ );
1010+
1011+ const auto profiles = parseProfiles (append).unwrap ();
1012+ assertEq (profiles.size (), 3UL );
1013+ assertEq (profiles.at (BuildProfile::Dev), devExpected);
1014+ assertEq (profiles.at (BuildProfile::Release), relProfileDefault);
1015+ assertEq (profiles.at (BuildProfile::Test), testExpected);
1016+ }
1017+ {
1018+ const toml::value overwrite = R"(
1019+ [profile.dev]
1020+ cxxflags = ["-A"]
1021+
1022+ [profile.test]
1023+ inherit-mode = "overwrite"
1024+ cxxflags = ["-B"]
1025+ )" _toml;
1026+
1027+ const Profile devExpected (
1028+ /* cxxflags=*/ { " -A" }, /* ldflags=*/ {}, /* lto=*/ false ,
1029+ /* debug=*/ true ,
1030+ /* compDb=*/ false , /* optLevel=*/ 0
1031+ );
1032+ const Profile testExpected (
1033+ /* cxxflags=*/ { " -B" }, /* ldflags=*/ {}, /* lto=*/ false ,
1034+ /* debug=*/ true ,
1035+ /* compDb=*/ false , /* optLevel=*/ 0
1036+ );
1037+
1038+ const auto profiles = parseProfiles (overwrite).unwrap ();
1039+ assertEq (profiles.size (), 3UL );
1040+ assertEq (profiles.at (BuildProfile::Dev), devExpected);
1041+ assertEq (profiles.at (BuildProfile::Release), relProfileDefault);
1042+ assertEq (profiles.at (BuildProfile::Test), testExpected);
1043+ }
1044+ {
1045+ const toml::value incorrect = R"(
1046+ [profile.test]
1047+ inherit-mode = "UNKNOWN"
1048+ )" _toml;
1049+
1050+ assertEq (
1051+ parseProfiles (incorrect).unwrap_err ()->what (),
1052+ " invalid inherit-mode: `UNKNOWN`"
1053+ );
1054+ }
9461055}
9471056
9481057static void
0 commit comments