Skip to content

Instantly share code, notes, and snippets.

@tnaka
Created December 17, 2010 02:27
Show Gist options
  • Save tnaka/744396 to your computer and use it in GitHub Desktop.
Save tnaka/744396 to your computer and use it in GitHub Desktop.
C/C++用Makefileテンプレート作成ツール
default $d $w
d -g
w -W -Wall
a -ansi -pedantic
o -O -DNDUBUG
p -pg
SDL `sdl-config --cflags --libs`
SDL_mixer -lSDL_mixer
X11 -L/usr/X11R6/lib -lX11
cv `pkg-config opencv --libs --cflags`
glut -lglut -lGLU -lGL
jpeg -ljpeg
wiimote -lwiimote
readline -lreadline -lcurses
math -lm

CやC++用のMakefileを自動生成するスクリプト。

オリジナルはshinhさんの書いたkati。 Makefile テンプレート作成ツール。

makedependを使ってヘッダファイルもmakefileに追加するように変更した。

Install

  • katiを~/binなどパスの通ったところに置き、chmod +x katiしておく。
  • .katiを~/に配置。

Usage

詳細は上記のshinhさんのページ参照。

  • カレントディレクトリにmain関数を含むtest.cがある状態で、 $ kati test.c または $ kati test すると、Makefile.katiが作られ、gccによりtestにコンパイルされる。単に $ kati すると、カレントディレクトリのソースが全てコンパイルされるはず。

  • mainがないソースは単にobjファイルにコンパイルされ、mainのあるソースのobjとまとめてリンクされるよう。

  • .katiには各行の一番左に項目名、右にそれに対応するオプションが書かれている。 項目名がソースのincludeに含まれていた場合、コンパイル時に右側のオプションが付加される。

#!/usr/bin/perl
use strict;
use FileHandle;
# setting
my %suf2com = (
'cc' => 'CXX',
'cpp' => 'CXX',
'cxx' => 'CXX',
'C' => 'CXX',
'c' => 'CC'
);
# load config
my $cfgfile = new FileHandle("$ENV{'HOME'}/.kati");
my %cfgs;
while (<$cfgfile>) {
/^([^\s]*)\s+(.*)$/;
$cfgs{$1} = $2;
}
# get targets
my @targets;
foreach (keys %suf2com) {
if (-e "$ARGV[0].$_") {
push @targets, "$ARGV[0].$_";
shift @ARGV;
last;
}
elsif (-e $ARGV[0]) {
if ($ARGV[0] =~ /\.$_$/) {
push @targets, $ARGV[0];
shift @ARGV;
last;
}
}
}
if (!$targets[0]) {
opendir DIR, ".";
foreach my $f (readdir DIR) {
foreach (keys %suf2com) {
if ($f =~ /\.$_$/) {
push @targets, $f;
}
}
}
}
if (!$targets[0]) {
print "cannot find target.\n";
exit 1;
}
# set CFLAGS and LDFLAGS
my $cflags;
my $ldflags;
my %feelings;
my @maintargets;
# default options
$feelings{'default'} = 1;
# get feeling options from include, and search main
foreach my $f (@targets) {
my $fh = new FileHandle $f;
while (<$fh>) {
if (/\#include/) {
foreach my $c (keys %cfgs) {
if (length $c > 1 && /$c/) {
$feelings{$c} = 1;
}
}
}
elsif (/ main\s*\(/) {
push @maintargets, $f;
last;
}
}
}
# get feeling options from argv
while (@ARGV) {
last if ($ARGV[0] =~ /^-/);
my $o = shift @ARGV;
if ($o =~ /^\+(.*)/) {
$feelings{$1} = -1;
}
else {
$feelings{$o} = 1;
}
}
# add feeling options
foreach (keys %feelings) {
if ($feelings{$_} == 1) {
feeling_add_opt($_);
}
}
# add argv options
add_opt(join ' ', @ARGV);
# create make file
my $make = new FileHandle("Makefile.kati", "w");
print $make "CFLAGS = $cflags\n";
print $make "LDFLAGS = $ldflags\n";
print $make "OBJS = ";
foreach (@targets) {
my $o = to_o($_);
print $make "$o ";
}
print $make "\n";
if ($maintargets[0]) {
print $make "EXES = ";
foreach (@maintargets) {
my $e = to_exe($_);
print $make "$e ";
}
print $make "\n";
print $make "TARGETS = ";
foreach (@targets) {
my $e = $_;
print $make "$e ";
}
print $make "\n";
print $make "\n";
print $make "all: \$(EXES)\n";
}
else {
print $make "\n";
print $make "all: \$(OBJS)\n";
}
print $make "\n";
foreach (@maintargets) {
my $e = to_exe($_);
my $c = $suf2com{get_suf($_)};
if ($maintargets[1]) {
my $o = to_o($_);
print $make "$e: $o\n";
print $make "\t\$($c) -o $e $o \$(LDFLAGS) \$(CFLAGS)\n";
}
else {
print $make "$e: \$(OBJS)\n";
print $make "\t\$($c) -o $e \$(OBJS) \$(LDFLAGS) \$(CFLAGS)\n";
}
print $make "\n";
}
my $suf = "";
foreach (@targets) {
if (!$suf) {
$suf = get_suf($_);
}
elsif ($suf ne get_suf($_)) {
$suf = "";
last;
}
}
if ($suf) {
print $make ".$suf.o:\n";
print $make "\t\$($suf2com{$suf}) -c \$(CFLAGS) \$<\n";
print $make "\n";
}
else {
foreach (@targets) {
my $o = to_o($_);
my $c = $suf2com{get_suf($_)};
print $make "$o: $_\n";
print $make "\t\$($c) -c $_ \$(CFLAGS)\n";
print $make "\n";
}
}
print $make ".PHONY: clean\n";
print $make "clean:\n";
print $make "\t\$(RM) -f \$(OBJS) \$(EXES)\n";
print $make "\n";
print $make "depend:\n";
print $make "\tmakedepend -f Makefile.kati -Y -- \$(CFLAGS) \$(LDFLAGS) -- \$(TARGETS)";
print $make "\n";
$make->close();
system("make -f Makefile.kati depend");
system("make -f Makefile.kati");
# feeling add cflags and ldflags
sub feeling_add_opt {
my $opt = shift;
if ($cfgs{$opt}) {
add_opt($cfgs{$opt});
delete $cfgs{$opt};
}
}
sub get_suf {
my $f = shift;
$f =~ /\.([^\.]*)$/;
return $1;
}
sub to_o {
my $f = shift;
$f =~ /^(.*)\.[^\.]*$/;
return "$1.o";
}
sub to_exe {
my $f = shift;
$f =~ /^(.*)\.[^\.]*$/;
return $1;
}
# is ld option?
sub is_ld {
my $opt = shift;
return $opt =~ /^-([lL]|Wl)/;
}
# add cflags and ldflags
sub add_opt {
my $opts = shift;
$opts =~ s/\`([^\`]*)\`/`$1`/ge;
foreach (split /\s+/, $opts) {
if (/^\$(.*)/) {
if ($feelings{$1} != -1) {
feeling_add_opt($1);
}
}
elsif (is_ld($_)) {
$ldflags .= "$_ ";
}
else {
$cflags .= "$_ ";
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment