#!/usr/bin/env perl
#
# Copyright (C) 2001-2022 Graeme Walker <graeme_walker@users.sourceforge.net>
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program 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 General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# ===
#
# make2cmake
#
# Parses the autoconf/automake artifacts throughout the source tree
# in order to generates simplistic 'cmake' files.
#
# Eg:
#   $ CXXFLAGS="-X" ./configure --with-whatever
#   $ bin/make2cmake
#   $ mkdir build
#   $ cd build
#   $ cmake ..
#   $ make VERBOSE=1
#
# The autoconf CXXFLAGS flow through to 'target_compile_options()' (etc)
# directives in the 'CMakeLists' files; other autoconf options flow
# through the 'config.status' file.
#
# See also: winbuild.pl
#

use strict ;
use Cwd ;
use FileHandle ;
use File::Find ;
use File::Basename ;
use File::Spec ;
use File::Copy ;
use lib dirname($0) ;
use ConfigStatus ;
use AutoMakeParser ;
$AutoMakeParser::debug = 0 ;
my $cfg_verbose = 1 ;
my $cfg_project = "emailrelay" ;

my $cs = new ConfigStatus( "config.status" ) ;
my %switches = $cs->switches() ;
my %vars = $cs->vars() ;
my %qt_config = (
	dirs => { "gui" => 1 } ,
	targets => { "emailrelay-gui.real" => 1 } ,
) ;

$vars{top_srcdir} = "." ;
$vars{top_builddir} = "." ;

create_cmake_files( $cfg_project , \%switches , \%vars , \%qt_config ) ;
create_empty_gconfig_header() ;

# ==

sub create_cmake_file
{
	my ( $project , $m , $switches , $vars , $qt_config ) = @_ ;

	my $path = join( "/" , dirname($m->path()) , "CMakeLists.txt" ) ;

	_log( "cmake-file=[$path]" ) ;
	my $fh = new FileHandle( $path , "w" ) or die ;

	my $link_options = $m->link_options() ;
	my $compile_options = $m->compile_options() ;
	$compile_options = join(" ",$compile_options,"-std=c++11") if( $compile_options !~ m/std=c++/ ) ;

	print $fh "# $path -- generated by $0\n" ;
	if( $project )
	{
		print $fh "cmake_minimum_required(VERSION 3.12)\n" ;
		print $fh "project($project)\n" ;
		print $fh "add_compile_options($compile_options)\n" ;
	}

	if( exists $qt_config->{dirs}->{basename(dirname($m->path()))} )
	{
		print $fh "\n" ;
		print $fh "find_package(Qt5 REQUIRED COMPONENTS Widgets Gui Core)\n" ;
	}

	print $fh "\n" if $m->subdirs() ;
	for my $subdir ( $m->subdirs() )
	{
		print $fh "add_subdirectory($subdir)\n" ;
	}

	my $definitions = join( " " , $m->definitions() ) ;
	my $includes = join( " " , "." , ".." , $m->includes($m->base()) ) ;

	my @libraries = $m->libraries() ;
	for my $library ( @libraries )
	{
		my $sources = join( " " , $m->sources( $library ) ) ;

		( my $library_key = $library ) =~ s/\.a$// ; $library_key =~ s/^lib// ;
		print $fh "\n" ;
		print $fh "add_library($library_key $sources)\n" ;
		print $fh "target_compile_options($library_key PUBLIC $compile_options)\n" ;
		print $fh "target_include_directories($library_key PUBLIC $includes)\n" ;
		print $fh "target_compile_definitions($library_key PUBLIC $definitions)\n" ;
		print $fh "set_target_properties($library_key PROPERTIES AUTOMOC ON)\n" if exists $qt_config->{targets}->{$library_key} ;
	}

	my @programs = $m->programs() ;
	for my $program ( @programs )
	{
		my $sources = join( " " , $m->sources( $program ) ) ;
		my $our_libs = join( " " , $m->our_libs( $program ) ) ;
		my $sys_libs = join( " " , $m->sys_libs( $program ) ) ;

		my $program_sources = join(" ",split(' ',"$sources")) ;
		my $program_includes = join(" ",split(' ',"$includes")) ;
		my $program_libs = join(" ",split(' ',"$our_libs $sys_libs")) ;

		print $fh "\n" ;
		print $fh "add_executable($program $program_sources)\n" ;
		print $fh "target_link_options($program PUBLIC $link_options)\n" ; # cmake 3.13
		print $fh "target_include_directories($program PUBLIC $program_includes)\n" ;
		print $fh "target_compile_definitions($program PUBLIC $definitions)\n" ;
		print $fh "target_link_libraries($program $program_libs)\n" ;
		print $fh "set_target_properties($program PROPERTIES AUTOMOC ON)\n" if exists $qt_config->{targets}->{$program} ;
	}

	$fh->close() or die ;
}

sub create_cmake_files
{
	my ( $project , $switches , $vars , $qt_config ) = @_ ;

	my @makefiles = AutoMakeParser::readall( "." , $switches , $vars , $cfg_verbose , "make2cmake: " ) ;
	my $first = 1 ;
	for my $m ( @makefiles )
	{
		create_cmake_file( $first?$project:undef , $m , $switches , $vars , $qt_config ) ;
		$first = 0 ;
	}
}

sub create_empty_gconfig_header
{
	my $path = "src/gconfig_defs.h" ;
	if( ! -f $path )
	{
		my $fh = new FileHandle( $path , "w" ) or die ;
		$fh->close() or die ;
	}
}

sub _log
{
	print "make2cmake: " , @_ , "\n" if $cfg_verbose ;
}

