@@ -316,10 +316,10 @@ static std::string tolf(const std::string &str) {
316316};
317317
318318struct Generator {
319- Generator (parser::Project &project) : project(project) {}
319+ Generator (const parser::Project &project) : project(project) {}
320320 Generator (const Generator &) = delete ;
321321
322- parser::Project &project;
322+ const parser::Project &project;
323323 std::stringstream ss;
324324 int indent = 0 ;
325325
@@ -383,11 +383,7 @@ struct Generator {
383383 for (const auto &itr : value) {
384384 const auto &condition = itr.first ;
385385 if (!condition.empty ()) {
386- if (project.conditions .count (condition) == 0 ) {
387- // TODO: somehow print line number information here?
388- throw std::runtime_error (" Unknown condition '" + condition + " '" );
389- }
390- cmd (" if" , condition)(RawArg (project.conditions [condition]));
386+ cmd (" if" , condition)(RawArg (project.conditions .at (condition)));
391387 }
392388
393389 if (!itr.second .empty ()) {
@@ -403,6 +399,27 @@ struct Generator {
403399 }
404400};
405401
402+ struct ConditionScope {
403+ Generator &gen;
404+ bool endif = false ;
405+
406+ ConditionScope (Generator &gen, const std::string &condition) : gen(gen) {
407+ if (!condition.empty ()) {
408+ gen.cmd (" if" , condition)(RawArg (gen.project .conditions .at (condition)));
409+ endif = true ;
410+ }
411+ }
412+
413+ ConditionScope (const ConditionScope &) = delete ;
414+ ConditionScope (ConditionScope &&) = delete ;
415+
416+ ~ConditionScope () {
417+ if (endif) {
418+ gen.cmd (" endif" )();
419+ }
420+ }
421+ };
422+
406423static bool vcpkg_valid_identifier (const std::string &name) {
407424 // prn|aux|nul|con|lpt[1-9]|com[1-9]|core|default
408425 auto is_reserved = [](const std::string &s) {
@@ -679,7 +696,14 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
679696 if (!project.contents .empty ()) {
680697 cmd (" include" )(" FetchContent" ).endl ();
681698 for (const auto &content : project.contents ) {
682- cmd (" message" )(" STATUS" , " Fetching " + content.name + " ..." );
699+ ConditionScope cs (gen, content.condition );
700+ std::string version_info = " " ;
701+ if (content.arguments .contains (" GIT_TAG" )) {
702+ version_info = " (" + content.arguments .at (" GIT_TAG" ) + " )" ;
703+ } else if (content.arguments .contains (" SVN_REVISION" )) {
704+ version_info = " (" + content.arguments .at (" SVN_REVISION" ) + " )" ;
705+ }
706+ cmd (" message" )(" STATUS" , " Fetching " + content.name + version_info + " ..." );
683707 ss << " FetchContent_Declare(\n\t " << content.name << " \n " ;
684708 for (const auto &arg : content.arguments ) {
685709 ss << " \t " << arg.first << " \n\t\t " << arg.second << " \n " ;
@@ -698,6 +722,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
698722 auto required = dep.required ? " REQUIRED" : " " ;
699723 auto config = dep.config ? " CONFIG" : " " ;
700724 auto components = std::make_pair (" COMPONENTS" , dep.components );
725+ ConditionScope cs (gen, dep.condition );
701726 cmd (" find_package" )(dep.name , version, required, config, components).endl ();
702727 }
703728 }
@@ -727,13 +752,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
727752 endl ();
728753 }
729754 for (const auto &subdir : project.subdirs ) {
730- if (!subdir.condition .empty ()) {
731- const auto &condition = subdir.condition ;
732- if (project.conditions .count (condition) == 0 ) {
733- throw std::runtime_error (" Unknown condition '" + condition + " ' for [subdir." + subdir.name + " ]" );
734- }
735- gen.cmd (" if" , condition)(RawArg (project.conditions [condition]));
736- }
755+ ConditionScope cs (gen, subdir.condition );
737756
738757 gen.handle_condition (subdir.include_before ,
739758 [&](const std::string &, const std::vector<std::string> &includes) { inject_includes (includes); });
@@ -743,23 +762,18 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
743762
744763 gen.handle_condition (subdir.include_after , [&](const std::string &, const std::vector<std::string> &includes) { inject_includes (includes); });
745764 gen.handle_condition (subdir.cmake_after , [&](const std::string &, const std::string &cmake) { inject_cmake (cmake); });
746-
747- if (!subdir.condition .empty ()) {
748- cmd (" endif" )();
749- }
750765 }
751766
752767 if (!project.targets .empty ()) {
753- for (const auto &target : project.targets ) {
768+ for (size_t i = 0 ; i < project.targets .size (); i++) {
769+ if (i > 0 ) {
770+ endl ();
771+ }
772+
773+ const auto &target = project.targets [i];
754774 comment (" Target " + target.name );
755775
756- if (!target.condition .empty ()) {
757- const auto &condition = target.condition ;
758- if (project.conditions .count (condition) == 0 ) {
759- throw std::runtime_error (" Unknown condition '" + condition + " ' for [target." + target.name + " ]" );
760- }
761- gen.cmd (" if" , condition)(RawArg (project.conditions [condition]));
762- }
776+ ConditionScope cs (gen, target.condition );
763777
764778 cmd (" set" )(" CMKR_TARGET" , target.name );
765779
@@ -901,13 +915,9 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
901915
902916 cmd (" unset" )(" CMKR_TARGET" );
903917 cmd (" unset" )(" CMKR_SOURCES" );
904-
905- if (!target.condition .empty ()) {
906- cmd (" endif" )();
907- }
908-
909- endl ();
910918 }
919+
920+ endl ();
911921 }
912922
913923 if (!project.tests .empty ()) {
@@ -922,6 +932,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
922932 auto working_directory = std::make_pair (" WORKING_DIRECTORY" , dir);
923933 auto command = std::make_pair (" COMMAND" , test.command );
924934 auto arguments = std::make_pair (" " , test.arguments );
935+ ConditionScope cs (gen, test.condition );
925936 cmd (" add_test" )(name, configurations, working_directory, command, arguments).endl ();
926937 }
927938 }
@@ -941,6 +952,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
941952 auto configs = std::make_pair (" CONFIGURATIONS" , inst.configs );
942953 auto destination = std::make_pair (" DESTINATION" , inst.destination );
943954 auto component = std::make_pair (" COMPONENT" , inst.targets .empty () ? " " : inst.targets .front ());
955+ ConditionScope cs (gen, inst.condition );
944956 cmd (" install" )(targets, dirs, files, configs, destination, component);
945957 }
946958 }
0 commit comments