#!/usr/bin/perl -I%PREFIX%/share/bsdbuild # # Copyright (c) 2008-2009 Hypertriton, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistribution of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Neither the name of CubeSoft Communications, nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # Read a BSDBuild Makefile on standard input and output the Premake script # which will be used by to generate IDE project files. # # The following BSDBuild variables are recognized: # # SUBDIR -> Recurse using Premake dopackage() # PROJECT -> Premake project name # PROJECT_GUID -> Project GUID # LIB -> Use as output library name # LIB_GUID -> Library GUID # LIB_LINKS -> Explicitely linked libraries (for non-Unix platforms) # LIB_SHARED -> Produce dynamic linkable libraries # LIB_STATIC -> Produce static libraries # PROG -> Use as output program name # PROG_GUID -> Program GUID # PROG_LINKS -> Explicitely linked libraries (for non-Unix platforms) # PROG_TYPE -> Set program interface ("GUI" or "CLI") # SRCS -> List of source files # CFLAGS -> Compiler options, used as follows: # # -I -> Add to package.includepaths # -D -> Add to package.defines use BSDBuild::Core; my $projFlav = ''; my $Error = ''; my %linkFn = (); my %V = (); sub Version { print << "EOF"; echo "BSDbuild %VERSION%" exit 1 EOF } sub DoProject { print << "EOF"; project.name = "$V{'PROJECT'}" EOF if (exists($V{'PROJECT_GUID'}) && $V{'PROJECT_GUID'}) { print "project.guid = \"$V{'PROJECT_GUID'}\"\n"; } if (exists($V{'SUBDIR'})) { my @subdirs = split(' ', $V{'SUBDIR'}); foreach my $subdir (@subdirs) { if ($subdir =~ /^\s*(.+)\*$/) { $subdir = $1; } unless ($subdir) { next; } print "dopackage(\"$subdir\")\n"; } } } sub DoPackage ($$$) { my ($name, $kind, $lang) = @_; unless ($name) { #print STDERR "Unable to determine package name\n"; exit (0); } print << "EOF"; package = newpackage() package.name = "$name" package.kind = "$kind" package.language = "$lang" EOF if (exists($V{'PROG_GUID'}) && $V{'PROG_GUID'}) { print "package.guid = \"$V{'PROG_GUID'}\"\n"; } elsif (exists($V{'LIB_GUID'}) && $V{'LIB_GUID'}) { print "package.guid = \"$V{'LIB_GUID'}\"\n"; } if ($ENV{'PROJFLAVOR'}) { $projFlav = $ENV{'PROJFLAVOR'}; } if ($ENV{'PROJINCLUDES'}) { foreach my $incl (split(' ', $ENV{'PROJINCLUDES'})) { print "dofile(\"$incl\")\n"; } } my $links = ''; if (exists($V{'PROG_LINKS'}) && $V{'PROG_LINKS'}) { $links = $V{'PROG_LINKS'}; } elsif (exists($V{'LIB_LINKS'}) && $V{'LIB_LINKS'}) { $links = $V{'LIB_LINKS'}; } if ($links) { foreach my $ln (split(' ', $links)) { print "tinsert(package.links,{\"$ln\"})\n"; } } if (exists($V{'SRCS'}) && $V{'SRCS'}) { print 'package.files = {', "\n"; foreach my $src (split(' ', $V{'SRCS'})) { if ($src =~ /^\s*(.+)\*$/) { $src = $1; } next unless $src; print "\t\"$src\",\n"; } print '}', "\n"; } if (exists($V{'CFLAGS'}) && $V{'CFLAGS'}) { my @cflags = split(' ', $V{'CFLAGS'}); foreach my $cflag (@cflags) { my $handled = 0; if ($cflag =~ /^-I\s*([\w\-\.\/]+)\s*$/) { print "tinsert(package.includepaths,". "{\"$1\"})\n"; next; } if ($cflag =~ /^-D\s*(\w+)\s*$/) { print "tinsert(package.defines,". "{\"$1\"})\n"; next; } if ($cflag =~ /^\${([\w\-\.]+)}$/) { $cflag = $1; } elsif ($cflag =~ /^\$([\w\-\.]+)$/) { $cflag = $1; } #foreach my $fn (values %cflagSubstFn) { # if (&$fn($projFlav, 'CFLAGS', $cflag)) { # $handled++; # } #} #if (!$handled) { # print STDERR "* CFLAGS: Not substituting: ". # "\"$cflag\"\n"; #} } } if (exists($V{'LIBS'}) && $V{'LIBS'}) { my @libs = split(' ', $V{'LIBS'}); foreach my $lib (@libs) { my $handled = 0; if ($lib =~ /^\${([\w\-\.]+)}$/) { $lib = $1; } elsif ($lib =~ /^\$([\w\-\.]+)$/) { $lib = $1; } #foreach my $fn (values %libsSubstFn) { # if (&$fn($projFlav, 'LIBS', $lib)) { # $handled++; # } #} #if (!$handled) { # print STDERR "Ignoring LIBS: $lib\n"; #} } } } sub ParseMakefile ($) { my $file = shift; my @lines = (); my $line = ''; my $incl; unless (open($incl, $file)) { $Error = "$file: $!"; return (0); } # Parse the Makefile looking for specific variables. foreach $_ (<$incl>) { chop; if (/^(.+)\\$/) { # Expansion $line .= $1; } else { # New line if ($line) { push @lines, $line . $_; $line = ''; } else { push @lines, $_; } } } foreach $_ (@lines) { if (/^\s*#/) { next; } if (/^\t/) { next; } s/\$\{(\w+)\}/$V{$1}/g; if (/^\s*(\w+)\s*=\s*"(.+)"$/ || /^\s*(\w+)\s*=\s*(.+)$/) { $V{$1} = $2; } elsif (/^\s*(\w+)\s*\+=\s*"(.+)"$/ || /^\s*(\w+)\s*\+=\s*(.+)$/) { if (exists($V{$1}) && $V{$1} ne '') { $V{$1} .= ' '.$2; } else { $V{$1} = $2; } } if (/^\s*include\s+(.+)$/) { my $incl = $1; if (!ParseMakefile($incl)) { $Error = "($incl): $Error"; return (0); } } } close($incl); return (1); } if (!ParseMakefile('-')) { print STDERR "$Error\n"; exit(1); } print << 'EOF'; -- -- Do not edit! -- This file was generated from Makefile by BSDbuild %VERSION%. -- -- To regenerate this file, get the latest BSDbuild release from -- http://hypertriton.com/bsdbuild/, the latest Premake release -- (v3 series) from http://premake.sourceforge.net/, and execute: -- -- $ make proj -- EOF # Infer the package language from the contents of ${SRCS}. my $packLang = 'c'; my %langs = (); if (exists($V{'SRCS'}) && $V{'SRCS'}) { foreach my $src (split(' ', $V{'SRCS'})) { if ($src =~ /\.c$/i) { $langs{'c'} = 1; } elsif ($src =~ /\.(cc|cpp)$/i) { $langs{'c++'} = 1; } elsif ($src =~ /\.cs$/i) { $langs{'c#'} = 1; } } } if (exists($langs{'c'})) { if (exists($langs{'c++'})) { print STDERR "*\n". "* WARNING: Package contains both C and C++\n". "* source files.\n". "*\n"; $packLang = 'c++'; } elsif (exists($langs{'c#'})) { print STDERR "*\n". "* WARNING: Package contains both C and C#\n". "* source files.\n". "*\n"; $packLang = 'c#'; } } elsif (exists($langs{'c++'})) { $packLang = 'c++'; } elsif (exists($langs{'c#'})) { $packLang = 'c#'; } # Scan BSDBuild modules for LINK operations. $INSTALLDIR = '%PREFIX%/share/bsdbuild'; $EmulEnv = $ENV{'PROJTARGET'}; $EmulOS = $ENV{'PROJOS'}; if (opendir(DIR, $INSTALLDIR.'/BSDBuild')) { foreach my $file (readdir(DIR)) { my $path = $INSTALLDIR.'/BSDBuild/'.$file; if ($file =~ /^\./ || $file =~ /^[A-Z]/ || !-f $path) { next; } if ($file !~ /^([\w\-\.]+)\.pm$/) { next; } my $modname = $1; do($path); if ($@) { print STDERR "Module failed: $modname: $@\n"; exit (1); } if (exists($LINK{$modname}) && defined($LINK{$modname})) { $linkFn{$modname} = $LINK{$modname}; } } closedir(DIR); } # Process projects and packages. if (exists($V{'PROJECT'}) && $V{'PROJECT'}) { DoProject(); } if (exists($V{'LIB'}) && $V{'LIB'}) { if (exists($V{'LIB_SHARED'}) && uc($V{'LIB_SHARED'}) eq 'YES') { DoPackage($V{'LIB'}.'_static', 'lib', $packLang); DoPackage($V{'LIB'}, 'dll', $packLang); } else { DoPackage($V{'LIB'}, 'lib', $packLang); } } elsif (exists($V{'PROG'}) && $V{'PROG'}) { if (exists($V{'PROG_TYPE'}) && uc($V{'PROG_TYPE'}) eq 'GUI') { DoPackage($V{'PROG'}, 'winexe', $packLang); } else { DoPackage($V{'PROG'}, 'exe', $packLang); } } elsif (!exists($V{'PROJECT'}) || !$V{'PROJECT'}) { print STDERR "None of ${PROJECT}, ${LIB} and ${PROG} are set.\n"; exit(1); }