#!/usr/bin/env python
#
# Copyright (C) 2010 Garth N. Wells.
# Licensed under the GNU LGPL Version 2.1.
#
# Generate CMakeLists.txt files in demo and test directories
# This script should be run from the top level directory.

import os
import subprocess

cmakelists_str = \
"""# Require CMake 2.8
cmake_minimum_required(VERSION 2.8)

project(%s)

# Set verbose output while testing CMake
#set(CMAKE_VERBOSE_MAKEFILE 1)

# Set CMake behavior
cmake_policy(SET CMP0004 OLD)

# Get DOLFIN configuration data (dolfin-config.cmake must be in DOLFIN_CMAKE_CONFIG_PATH)
find_package(dolfin)

# Default build type (can be overridden by user)
if (NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
    "Choose the type of build, options are: Debug MinSizeRel Release RelWithDebInfo." FORCE)
endif()

# Compiler definitions
add_definitions(${DOLFIN_CXX_DEFINITIONS})

# Add special DOLFIN compiler flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DOLFIN_CXX_FLAGS}")

# Include directories
include_directories(${DOLFIN_INCLUDE_DIRS} ${DOLFIN_3RD_PARTY_INCLUDE_DIRS})

# Executable
add_executable(%s %s)

# Target libraries
target_link_libraries(%s ${DOLFIN_LIBRARIES} ${DOLFIN_3RD_PARTY_LIBRARIES})
"""

def generate_cmake_files(subdirectory, executable_suffix):
    """Search for C++ code and write CMakeLists.txt files"""
    cwd = os.getcwd()
    for root, dirs, files in os.walk(cwd + "/" + subdirectory):

        executable_names = set()

        # For 'cpp' directories, get list of .cpp files
        if "cpp" in dirs:
            cpp_files = []
            program_dir = root + "/cpp"
            tmp, program_name = os.path.split(root)
            for f in os.listdir(program_dir):
                filename, extension = os.path.splitext(f)
                if extension == ".cpp":
                    cpp_files.append(f)

            # Name of demo and cpp source files
            program_name += executable_suffix
            cpp_files = ' '.join(cpp_files)

            # Check for duplicate executable names
            if program_name not in executable_names:
                executable_names.add(program_name)
            else:
                print "Warning: duplicate executable names found when generating CMakeLists.txt files."

            # Write file
            with open(program_dir + "/CMakeLists.txt", 'w') as f:
                print "Creating CMakeLists.txt file:", program_name, program_dir
                f.write( cmakelists_str % (program_name, program_name, cpp_files, program_name) )

            # FIXME: add command line option for adding files
            # Add to version control
            #subprocess.call(["bzr", "add", program_dir + "/CMakeLists.txt"])


# Generate CMakeLists.text files
sub_directories = [('demo', '-demo'), ('test', '-test'), ('bench', '-bench')]
for sub_dir in sub_directories:
    generate_cmake_files(sub_dir[0], sub_dir[1])
