def gen_cmakelists(project_name, project_language, min_cmake_version, default_build_type, relative_path, modules):
    """
    Generate CMakeLists.txt.
    """
    import os

    s = []

    s.append(autogenerated_notice())

    s.append('\n# set minimum cmake version')
    s.append('cmake_minimum_required(VERSION {0} FATAL_ERROR)'.format(min_cmake_version))

    s.append('\n# project name')
    s.append('project({0} {1})'.format(project_name, project_language))

    s.append('\n# do not rebuild if rules (compiler flags) change')
    s.append('set(CMAKE_SKIP_RULE_DEPENDENCY TRUE)')

    build_type_capitalized = {'debug': 'Debug',
                              'release': 'Release',
                              'relwithdebinfo': 'RelWithDebInfo',
                              'minsizerel': 'MinSizeRel'}

    _build_type = build_type_capitalized[default_build_type]
    s.append('\n# if CMAKE_BUILD_TYPE undefined, we set it to {0}'.format(_build_type))
    s.append('if(NOT CMAKE_BUILD_TYPE)')
    s.append('    set(CMAKE_BUILD_TYPE "{0}")'.format(_build_type))
    s.append('endif()')

    if len(modules) > 0:
        s.append('\n# directories which hold included cmake modules')

    module_paths = [module.path for module in modules]
    module_paths.append('downloaded')  # this is done to be able to find fetched modules when testing
    module_paths = list(set(module_paths))
    module_paths.sort()  # we do this to always get the same order and to minimize diffs
    for directory in module_paths:
        rel_cmake_module_path = os.path.join(relative_path, directory)
        # on windows cmake corrects this so we have to make it wrong again
        rel_cmake_module_path = rel_cmake_module_path.replace('\\', '/')
        s.append('set(CMAKE_MODULE_PATH ${{CMAKE_MODULE_PATH}} ${{PROJECT_SOURCE_DIR}}/{0})'.format(rel_cmake_module_path))

    if len(modules) > 0:
        s.append('\n# included cmake modules')
    for module in modules:
        s.append('include({0})'.format(os.path.splitext(module.name)[0]))

    return s