
load(qt_functions)

contains(TEMPLATE, subdirs) {
    for(build, QMAKE_EXCLUSIVE_BUILDS) {
        prepareRecursiveTarget($$build)
        QMAKE_EXTRA_TARGETS += $$build
    }
} else {
    # Recursively combines a list of exclusive builds into combinations
    # of non-exclusive builds (separated by a ':' character), eg the
    # list [debug, release, static, shared] will result in the four
    # combinations [debug:static, debug:shared, release:static,
    # release:shared].
    defineReplace(combineExclusiveBuilds) {
        permutationBuilds = $$1
        existingBuilds = $$2

        isEmpty(permutationBuilds): \
            # Exit-condition, no more recursing
            return($$existingBuilds)

        # Choose the first build of the permutations and use the set of exclusive
        # builds associated with that build as the list of existing builds. This
        # partitions the permutations into one set of exclusive builds + the rest
        # of the unknown permutations.
        newExistingBuilds = $$eval($$first(permutationBuilds).exclusive)
        permutationBuilds -= $$newExistingBuilds

        # Recursively compute the combination of these two sets
        recursiveCombination = $$combineExclusiveBuilds($$permutationBuilds, $$newExistingBuilds)

        isEmpty(existingBuilds): \
            # No need to combine further
            return($$recursiveCombination)

        result =
        for(existingBuild, existingBuilds) {
            for(combination, recursiveCombination): \
                result += "$${existingBuild}:$${combination}"
        }
        return($$result)
    }

    buildCombinations = $$combineExclusiveBuilds($$QMAKE_EXCLUSIVE_BUILDS)

    for(combination, buildCombinations) {
        builds = $$split(combination, :)
        key =
        config =
        target =
        priority =
        for(build, builds) {
            key = $${key}$$eval($${build}.name)
            config *= $$eval($${build}.CONFIG) $${build} $$eval($${build}.name)Build
            target += $$eval($${build}.target)

            # If a build has been prioritized through CONFIG we prefer that
            CONFIG($$build, $$join($${build}.exclusive, |)): \
                priority += 1
        }

        $${key}.name = $$key
        $${key}.target = $$join(target, -)
        $${key}.CONFIG = $$config
        $${key}.builds = $$builds

        BUILDS.$$size(priority) += $$key

        # Add makefile targets for each exclusive build that will aggregate all targets
        # that include the exclusive build. This matches the targets in the SUBDIR files
        # so that you can recursivly build a single exclusive build.
        !build_pass:count(builds, 1, >) {
            for(build, builds) {
                $${build}.depends += $$eval($${key}.target)
                QMAKE_EXTRA_TARGETS *= $$build
            }
        }
    }

    BUILDS =
    priority =
    for(ever) {
        # Keep the order in BUILDS matching the priority from CONFIG, so that the first
        # entry in BUILDS will be the first/default target when not CONFIG(build_all).
        BUILDS = $$eval(BUILDS.$$size(priority)) $$BUILDS
        count(BUILDS, $$size(buildCombinations), >=): break()
        priority += 1
    }

    build_pass|fix_output_dirs {
        !build_pass {
            # The builds are sorted by priority based on the current config
            # so choosing the first one gives us the most appropriate build.
            BUILD_PASS = $$first(BUILDS)
        }

        for(dir, QMAKE_DIR_REPLACE) {

            # Limit builds to ones that should affect the current $$dir
            builds =
            for(build, $${BUILD_PASS}.builds) {
                equals(dir, DESTDIR) {
                    !$$join($${build}.exclusive, _and_)_target: \
                        next()
                }

                builds += $$build
            }

            isEmpty(builds): \
                next()

            affixes =
            for(build, builds): \
                affixes += $$eval($${build}.dir_affix)
            full_dir_affix = $$join(affixes, -)

            isEmpty($$dir)|isEqual($$dir, .) {
                # Use affix directly
                $$dir = $$full_dir_affix
                next()
            }

            contains(QMAKE_DIR_REPLACE_SANE, $$dir) {
                # Suffix output dir
                $$dir = $$clean_path($$eval($$dir)/$$full_dir_affix)
            } else {
                # "Compatibility mode" with QTBUG-491
                for(build, builds) {
                    did_replace = false
                    build_affix = $$eval($${build}.dir_affix)
                    for(exclusive, $${build}.exclusive) {
                        equals(exclusive, $$build): \
                            next()

                        exclusive_affix = $$eval($${exclusive}.dir_affix)
                        contains($$dir, .*$${exclusive_affix}.*) {
                            $$dir ~= s/$${exclusive_affix}/$${build_affix}/gi
                            did_replace = true
                        }
                    }
                    $$did_replace: next()

                    # Append (as subdir or as suffix)
                    !build_pass {
                        dir_affix = $$eval($${build}.dir_affix)
                        !contains($$dir, .*$${dir_affix}.*) {
                            contains($$dir, .*/$) {
                                # Subdir
                                $$dir = $$eval($$dir)$$dir_affix
                            } else {
                                # Suffix
                                $$dir = $$eval($$dir)-$${dir_affix}
                            }
                        }
                    }
                }
            }
        }
    }
}
