#!/usr/bin/env python
#
# Copyright (C) 2010 Garth N. Wells
#
# This file is part of DOLFIN.
#
# DOLFIN is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DOLFIN is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with DOLFIN. If not, see <http://www.gnu.org/licenses/>.
#
# 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_prefix):
    """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_prefix + program_name
            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])
