| 604 | |
| 605 | private: |
| 606 | std::string cmake_condition(const std::string &condition) { |
| 607 | // HACK: this replaces '$<name>' with the value of the 'name' condition. We can safely |
| 608 | // reuse the generator expression syntax, because it is not valid in CMake conditions. |
| 609 | // TODO: properly handle quoted arguments (using a simple state machine): |
| 610 | // https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#quoted-argument |
| 611 | std::string result = ""; |
| 612 | bool in_replacement = false; |
| 613 | std::string temp; |
| 614 | for (size_t i = 0; i < condition.length(); i++) { |
| 615 | if (in_replacement) { |
| 616 | if (condition[i] == '>') { |
| 617 | in_replacement = false; |
| 618 | if (temp.empty()) { |
| 619 | throw std::runtime_error("Empty replacement in condition '" + condition + "'"); |
| 620 | } |
| 621 | auto found = project.conditions.find(temp); |
| 622 | if (found == project.conditions.end()) { |
| 623 | throw std::runtime_error("Unknown condition '" + temp + "' in replacement"); |
| 624 | } |
| 625 | auto has_space = found->second.find(' ') != std::string::npos; |
| 626 | if (has_space) { |
| 627 | result += '('; |
| 628 | } |
| 629 | result += found->second; |
| 630 | if (has_space) { |
| 631 | result += ')'; |
| 632 | } |
| 633 | temp.clear(); |
| 634 | } else { |
| 635 | temp += condition[i]; |
| 636 | } |
| 637 | } else if (condition[i] == '$' && i + 1 < condition.length() && condition[i + 1] == '<') { |
| 638 | i++; |
| 639 | in_replacement = true; |
| 640 | } else { |
| 641 | result += condition[i]; |
| 642 | } |
| 643 | } |
| 644 | if (!temp.empty()) { |
| 645 | throw std::runtime_error("Unterminated replacement in condition '" + condition + "'"); |
| 646 | } |
| 647 | return result; |
| 648 | } |
| 649 | }; |
| 650 | |
| 651 | struct ConditionScope { |