[RFC] [PATCH] GNU make based build system for Winelib applications

Kirill Smelkov kirr at mns.spb.ru
Sun Sep 2 07:05:35 CDT 2007


Hello Wine developers, Francois!

I am going to port some Win32 applications to GNU/Linux and though it would be 
useful to improve the build system for Winelib applications.


Current status and Motivation
=============================

1. Wine in-tree Makefiles for programs & dlls are pretty much good and
   maintainable, but they lack C++ support.
2. Initial approach taken by winemaker (I used it in 2003-2004) was to adapt
   Wine's make rules to support C++ .
3. At present winemaker dropped supplying above mentioned rules and generates
   very simple makefiles. To me this approach have several problems:

- lack of dependency tracking
- hard to maintain Makefiles.
  The rules generated are substituted in each Makefile instead of being in one
  place.
- good as a starting point, but not a complete solution.


Winemaker already relies on GNU toolchain (in form of gcc and g++), and I
though::

  Why not use GNU make with all available extensions when necessary, and
  deploy a simple full-featured build system for Winelib based applications

The result is presented here for public review.
Comments, suggestions?



Features
========

* support C, C++ and resource files.
* automatic dependency tracking for C and C++.
* beautified build output (to increase SNR and concentrate on errors and
  warnings).
* winemaker patches provided (although I don't know Perl -- help needed, 
Francois?).
* Tested with GNU make 3.81. This version of GNU make was released in 2006 and
  is present in all recent Linux distributions.

Usage example
=============

I attach winelib-gnu-make.tar.gz where an interested reader can see Winemake 
build system usage.

For usage example see directory clock+wow32/ . There I provide example of how
to build 1 program and 2 dlls.

Original clock.exe & wow32.dll processed by winemaker are located in misc/ for 
comparison.
-------------- next part --------------
>From 0d19d4bd95a97dc7d582872f22f4b393521709f8 Mon Sep 17 00:00:00 2001
From: Kirill Smelkov <kirr at mns.spb.ru>
Date: Sun, 2 Sep 2007 15:51:21 +0400
Subject: [PATCH] winemake: GNU make based build system for Winelib applications

---
 include/Makefile.in           |    4 +
 include/wine/Winemake.include |  265 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 269 insertions(+), 0 deletions(-)

diff --git a/include/Makefile.in b/include/Makefile.in
index 4607006..80fcb6a 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -64,9 +64,13 @@ IDL_H_SRCS = \
 IDL_TLB_SRCS = \
 	stdole2.idl
 
+WINEMAKE_SRCS = \
+	wine/Winemake.include
+
 SRCDIR_INCLUDES = \
 	$(IDL_TLB_SRCS) \
 	$(IDL_H_SRCS) \
+	$(WINEMAKE_SRCS) \
 	accctrl.h \
 	aclapi.h \
 	adshlp.h \
diff --git a/include/wine/Winemake.include b/include/wine/Winemake.include
new file mode 100644
index 0000000..f9d9f0d
--- /dev/null
+++ b/include/wine/Winemake.include
@@ -0,0 +1,265 @@
+# =============================================================================
+# GNU make based build system for Winelib applications
+# Some of ideas taken from Kbuild, Wine build system & Automake
+#
+# Started: 2007 Kirill Smelkov <kirr at mns.spb.ru>
+
+
+# Do not:
+# o  use make's built-in rules and variables
+#    (this increases performance and avoid hard-to-debug behavour);
+# o  print "Entering directory ...";
+# XXX As it is, MAKEFLAGS affects only the next-level invocations of make.
+# XXX At least .SUFFIXES: clear built-in rules for top-level.
+MAKEFLAGS += -rR --no-print-directory
+
+# Do not use built-in rules
+.SUFFIXES:
+
+# =============================================================================
+# Config
+CC	:= winegcc
+CXX	:= wineg++
+RC	:= wrc
+
+RM	:= rm -f
+LN_S	:= ln -sf
+
+DEPDIR	:= .deps
+
+ifeq ($(MAKELEVEL),0)
+export TOP := $(CURDIR)
+
+# hook winemake into make's path, so Makefiles in subdirectories can just do
+# 'include Winemake.include'
+winemake_root:= $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
+MAKEFLAGS += -I $(winemake_root)
+endif
+
+# load build configuration
+-include $(TOP)/.config
+
+
+# =============================================================================
+# Build internals
+
+# quiet/verbose
+V	?= 0
+ifneq ($(V),0)
+  quiet	:=
+  Q	:=
+else
+  quiet	:= quiet_
+  Q	:= @
+endif
+
+
+# Main goal
+.PHONY	: all $(SUBDIRS)
+all	: $(SUBDIRS) $(MODULES)
+
+$(SUBDIRS):
+	$(Q)$(MAKE) -C $@
+
+# Rules for cleaning
+CLEAN_FILES     = y.tab.c y.tab.h lex.yy.c core *.orig *.rej \
+                  \\\#*\\\# *~ *% .\\\#*
+
+clean:: $(SUBDIRS:%=%/__clean__) $(EXTRASUBDIRS:%=%/__clean__)
+	$(call qpretty,CLEAN   $(if $(curdir),$(curdir),.))
+	$(Q)$(RM) $(CLEAN_FILES)
+	$(Q)$(RM) -R $(DEPDIR)
+
+$(SUBDIRS:%=%/__clean__): FORCE
+	$(Q)$(MAKE) -C $(dir $@) clean
+
+
+.PHONY	: FORCE
+
+# =============================================================================
+
+# canonicalize a name
+# UC: $(call canonicalize, foo-xxx.exe)  ->  foo_xxx_exe
+canonicalize = $(subst -,_,$(subst .,_,$1))
+
+# handy canonical arguments
+1C	= $(call canonicalize,$1)
+*C	= $(call canonicalize,$*)
+ at C	= $(call canonicalize,$@)
+
+# handy variables
+1C_SRC	= $($(1C)_SRC)
+ at C_LINK	= $($(@C)_LINK)
+
+# $! == eye-candy $@ , $(1!) == eye-candy $1
+curdir	:= $(patsubst $(TOP)%,%,$(CURDIR))
+curdir	:= $(patsubst /%,%,$(curdir))
+curdir	:= $(curdir)$(if $(curdir),/)
+!	= $(curdir)$@
+1!	= $(curdir)$1
+
+
+# Utils
+
+# filter list items by extension
+# UC: $(call __filter-ext,.cxx,hello.c abc.C arm.cxx)  ->  arm.cxx
+__filter-ext= $(filter %$1,$2)
+
+# filter list items by extension, then substiture extension for filtered items
+# UC: $(call __subst-ext,.c,.o,hello.c abc.cpp)  ->  hello.o
+__subst-ext= $(patsubst %$1,%$2,$(call __filter-ext,$1,$3))
+
+# C++ has so many extensions ...
+c++-ext	  := cpp cxx cc C c++
+
+# extract X-sources from sources list
+# UC: $(call __src-c, hello.c hi.cpp ...)  ->  hello.c
+__src-c	  = $(filter %.c,$1)
+__src-cxx = $(strip $(foreach ext,$(c++-ext),$(filter %.$(ext),$1)))
+__src-rc  = $(filter %.rc,$1)
+__src-spec= $(filter %.spec,$1)
+
+# extract X-sources from a module
+# UC: $(call src-c,foo.exe)
+src-c	= $(call __src-c,$(1C_SRC))
+src-cxx	= $(call __src-cxx,$(1C_SRC))
+src-rc	= $(call __src-rc,$(1C_SRC))
+src-spec= $(call __src-spec,$(1C_SRC))
+
+# list of unknown sources for a module
+# it is an error when this list is not empty
+src-unknown = $(filter-out $(foreach srctype,c cxx rc spec,$(call src-$(srctype),$1)), $(1C_SRC))
+
+
+# extract X-objects from source list
+# UC: $(call objs-c, hello.c hi.cpp ...)  ->  hello.o
+__objs-c  = $(call __subst-ext,.c,.o,$1)
+__objs-cxx= $(foreach ext,$(c++-ext),$(call __subst-ext,.$(ext),.o,$1))
+__objs-rc = $(call __subst-ext,.rc,.res,$1)
+
+# extract X-objects from a module
+# UC: objs = $(call objs-c, foo)
+objs-c	= $(call __objs-c,$(1C_SRC))
+objs-cxx= $(call __objs-cxx,$(1C_SRC))
+objs-rc	= $(call __objs-rc,$(1C_SRC))
+
+
+# Autogen modules templates
+__SRC_UNKNOWN	:=
+
+define MODULE_template
+$(1C)_SRC_C	:= $$(call src-c,$1)
+$(1C)_SRC_CXX	:= $$(call src-cxx,$1)
+$(1C)_SRC_RC	:= $$(call src-rc,$1)
+$(1C)_SRC_SPEC	:= $$(call src-spec,$1)
+
+$(1C)_OBJS	:= $(foreach lang,c cxx rc,$$(call objs-$(lang),$1))
+
+# link command (C++ programs have to be linked by C++ compiler)
+$(1C)_LINK	:= $$(if $$($(1C)_SRC_CXX),$(CXX),$(CC))
+
+# explicit dependencies (to keep objects precious)
+$1	: $$($(1C)_OBJS)
+
+# objects want $(DEPDIR)
+$$($(1C)_OBJS)	: | $(DEPDIR)
+
+# include auto-generated dependencies
+-include $$(foreach obj,$$(basename $$($(1C)_OBJS)),$(DEPDIR)/$$(obj).d)
+
+$(1C)_SRC_UNKNOWN:=$$(call src-unknown,$1)
+__SRC_UNKNOWN	+= $$($(1C)_SRC_UNKNOWN)
+clean::
+	$$(call qpretty,CLEAN   $(1!))
+	$(Q)$(RM) $$($(1C)_OBJS) $1.so $1
+endef
+
+$(foreach module,$(MODULES),$(eval $(call MODULE_template,$(module))))
+
+# Verify whether all sources provided are of known type
+__SRC_UNKNOWN	:= $(strip $(__SRC_UNKNOWN))
+ifneq "$(__SRC_UNKNOWN)" ""
+$(error E: Source(s) of unknown type: [ $(__SRC_UNKNOWN) ] )
+endif
+
+
+# =============================================================================
+# Common
+
+# Convenient variables
+comma   := ,
+squote  := '
+empty   :=
+space   := $(empty) $(empty)
+
+###
+# Escape single quote for use in echo statements
+escsq = $(subst $(squote),'\$(squote)',$1)
+
+# echo command.
+# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
+echo-cmd = $(if $($(quiet)cmd_$(1)),\
+	echo '  $(call escsq,$($(quiet)cmd_$(1)))';)
+
+# echo pretty string [only in quiet mode]
+qpretty = $(if $(Q), at echo '  $1')
+
+# printing commands
+cmd	= @$(echo-cmd) $(cmd_$(1))
+
+# =============================================================================
+# Rules
+
+quiet_cmd_mkdir = MKDIR   $!
+      cmd_mkdir = mkdir -p $@
+
+# XXX do we need '-MT $@ -MP' here?
+cc_dep_opts	= -MD -MF $(@:%.o=$(DEPDIR)/%.d)
+
+quiet_cmd_c_c	= CC      $!
+      cmd_c_c	= $(CC) -c $(CFLAGS) $(CEXTRA) $(DEFINCL) -o $@ $<  $(cc_dep_opts)
+
+quiet_cmd_cxx_c	= C++     $!
+      cmd_cxx_c	= $(CXX) -c $(CXXFLAGS) $(CXXEXTRA) $(DEFINCL) -o $@ $<  $(cc_dep_opts)
+
+# TODO add dependency generation for RC command
+quiet_cmd_rc_x	= RC      $!
+      cmd_rc_x	= $(RC) $(RCFLAGS) $(RCEXTRA) $(DEFINCL) -fo$@ $<
+
+
+$(DEPDIR):
+	$(call cmd,mkdir)
+
+%.o	: %.c
+	$(call cmd,c_c)
+
+define rule_cxx_ext
+%.o	: %.$1
+	$$(call cmd,cxx_c)
+endef
+$(foreach ext,$(c++-ext),$(eval $(call rule_cxx_ext,$(ext))))
+
+%.res	: %.rc
+	$(call cmd,rc_x)
+
+
+DEFLIB	:= $(LIBRARY_PATH) $(LIBRARIES) $(DLL_PATH)
+
+quiet_cmd_link_exe = EXE     $!
+      cmd_link_exe = $(@C_LINK) $(LDFLAGS) $(LDEXTRA) -o $@.so $+ $(DEFLIB) $(DLLS:%=-l%) $(LIBS:%=-l%)
+      cmd_exe_fixup= echo -e '\#!/bin/sh\n\nexec wine $$0.so\n' > $@	&& chmod a+x $@
+
+quiet_cmd_link_dll = DLL     $!
+      cmd_link_dll = $(@C_LINK) $(LDFLAGS) $(LDEXTRA) -shared -o $@.so $+ $(DEFLIB) $(DLLS:%=-l%) $(LIBS:%=-l%)
+      cmd_dll_fixup= $(LN_S) $(@F).so $(@D)/$(@F:.so=)
+
+.SECONDEXPANSION:
+%.exe	:
+	$(call cmd,link_exe)
+	$(call cmd,exe_fixup)
+
+%.dll	: $$($$(@C)_SRC_SPEC)
+	$(call cmd,link_dll)
+	$(call cmd,dll_fixup)
+
+
-- 
1.4.4.4

-------------- next part --------------
>From b32468fe4a97cff58b2dc4b947d01cd319b82834 Mon Sep 17 00:00:00 2001
From: Kirill Smelkov <kirr at mns.spb.ru>
Date: Sun, 2 Sep 2007 15:52:39 +0400
Subject: [PATCH] winemaker: adapt to using Winemake.include

As I don't know Perl,
This patch requires help from winemaker maintainer.
---
 tools/winemaker |  163 +++++++++++++++----------------------------------------
 1 files changed, 44 insertions(+), 119 deletions(-)

diff --git a/tools/winemaker b/tools/winemaker
index 960804d..4bde7e4 100755
--- a/tools/winemaker
+++ b/tools/winemaker
@@ -19,7 +19,7 @@ use strict;
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 #
 
-my $version="0.6.0";
+my $version="0.7.0";
 
 use Cwd;
 use File::Basename;
@@ -204,6 +204,9 @@ my $T_LIBRARIES=16;
 # The list of dependencies between targets
 my $T_DEPENDS=17;
 
+##
+# List of linker options
+my $T_LDEXTRA = 18;
 
 # The following constants define the recognized types of target
 
@@ -270,6 +273,7 @@ sub target_init($)
   @$target[$T_DLLS]=[];
   @$target[$T_LIBRARY_PATH]=[];
   @$target[$T_LIBRARIES]=[];
+  @$target[$T_LDEXTRA]=[];
 }
 
 
@@ -799,7 +803,6 @@ sub source_scan_directory($$$$)
       push @local_depends,"$target_name.so";
       push @local_dlls,$target_name;
       my $canon=canonize($target_name);
-      push @{@$target[$T_LDFLAGS]},("-shared","\$(${canon}_MODULE:%=%.spec)");
     } else {
       @$target[$T_TYPE]=$opt_target_type;
       push @exe_list,$target;
@@ -912,6 +915,7 @@ sub source_scan_directory($$$$)
   if ((@$project_settings[$T_FLAGS] & $TF_NOMSVCRT) == 0) {
     push @{@$project_settings[$T_CEXTRA]},"-mno-cygwin";
     push @{@$project_settings[$T_CXXEXTRA]},"-mno-cygwin";
+    push @{@$project_settings[$T_LDEXTRA]},"-mno-cygwin";
   }
 
   if (@$project_settings[$T_FLAGS] & $TF_MFC) {
@@ -1527,7 +1531,7 @@ sub generate_list($$$;$)
   my $first=$name;
 
   if ($name) {
-    printf FILEO "%-22s=",$name;
+    printf FILEO "%-21s:=",$name;
   }
   if (defined $list) {
     foreach my $item (@$list) {
@@ -1560,6 +1564,7 @@ sub generate_project_files($)
   my $project_settings=@$project[$P_SETTINGS];
   my @dll_list=();
   my @exe_list=();
+  my @all_list=();
 
   # Then sort the targets and separate the libraries from the programs
   foreach my $target (sort { @$a[$T_NAME] cmp @$b[$T_NAME] } @{@$project[$P_TARGETS]}) {
@@ -1569,6 +1574,9 @@ sub generate_project_files($)
       push @exe_list,$target;
     }
   }
+
+  push @all_list, @exe_list, @dll_list;
+
   @$project[$P_TARGETS]=[];
   push @{@$project[$P_TARGETS]}, @dll_list;
   push @{@$project[$P_TARGETS]}, @exe_list;
@@ -1582,7 +1590,7 @@ sub generate_project_files($)
   print FILEO "### Generated by Winemaker\n";
   print FILEO "\n\n";
 
-  generate_list("SRCDIR",1,[ "." ]);
+  #generate_list("SRCDIR",1,[ "." ]);
   if (@$project[$P_PATH] eq "") {
     # This is the main project. It is also responsible for recursively
     # calling the other projects
@@ -1597,20 +1605,18 @@ sub generate_project_files($)
 		  });
   }
   if (@{@$project[$P_TARGETS]} > 0) {
-    generate_list("DLLS",1,\@dll_list,sub
+    generate_list("MODULES",1,\@all_list,sub
 		  {
 		    return @{$_[0]}[$T_NAME];
 		  });
-    generate_list("EXES",1,\@exe_list,sub
-		  {
-		    return "@{$_[0]}[$T_NAME]";
-		  });
+
     print FILEO "\n\n\n";
 
     print FILEO "### Common settings\n\n";
     # Make it so that the project-wide settings override the global settings
     generate_list("CEXTRA",1,@$project_settings[$T_CEXTRA]);
     generate_list("CXXEXTRA",1,@$project_settings[$T_CXXEXTRA]);
+    generate_list("LDEXTRA",1,@$project_settings[$T_LDEXTRA]);
     generate_list("RCEXTRA",1,@$project_settings[$T_RCEXTRA]);
     generate_list("INCLUDE_PATH",1,@$project_settings[$T_INCLUDE_PATH]);
     generate_list("DLL_PATH",1,@$project_settings[$T_DLL_PATH]);
@@ -1622,6 +1628,7 @@ sub generate_project_files($)
                            @{@$project_settings[$T_SOURCES_CXX]}+
                            @{@$project_settings[$T_SOURCES_RC]};
     my $no_extra=($extra_source_count == 0);
+    # XXX what to do with extra src ???
     if (!$no_extra) {
       print FILEO "### Extra source lists\n\n";
       generate_list("EXTRA_C_SRCS",1,@$project_settings[$T_SOURCES_C]);
@@ -1638,121 +1645,39 @@ sub generate_project_files($)
       my $canon=canonize("@$target[$T_NAME]");
       $canon =~ s+_so$++;
 
-      generate_list("${canon}_MODULE",1,[@$target[$T_NAME]]);
-      generate_list("${canon}_C_SRCS",1,@$target[$T_SOURCES_C]);
-      generate_list("${canon}_CXX_SRCS",1,@$target[$T_SOURCES_CXX]);
-      generate_list("${canon}_RC_SRCS",1,@$target[$T_SOURCES_RC]);
-      generate_list("${canon}_LDFLAGS",1,@$target[$T_LDFLAGS]);
-      generate_list("${canon}_DLL_PATH",1,@$target[$T_DLL_PATH]);
-      generate_list("${canon}_DLLS",1,@$target[$T_DLLS]);
-      generate_list("${canon}_LIBRARY_PATH",1,@$target[$T_LIBRARY_PATH]);
-      generate_list("${canon}_LIBRARIES",1,@$target[$T_LIBRARIES]);
-      print FILEO "\n";
-      generate_list("${canon}_OBJS",1,["\$(${canon}_C_SRCS:.c=.o)","\$(${canon}_CXX_SRCS:.cpp=.o)","\$(${canon}_RC_SRCS:.rc=.res)"]);
-      print FILEO "\n\n\n";
-    }
-    print FILEO "### Global source lists\n\n";
-    generate_list("C_SRCS",$no_extra,@$project[$P_TARGETS],sub
-		  {
-		    my $canon=canonize(@{$_[0]}[$T_NAME]);
-		    $canon =~ s+_so$++;
-		    return "\$(${canon}_C_SRCS)";
-		  });
-    if (!$no_extra) {
-      generate_list("",1,[ "\$(EXTRA_C_SRCS)" ]);
-    }
-    generate_list("CXX_SRCS",$no_extra,@$project[$P_TARGETS],sub
-		  {
-		    my $canon=canonize(@{$_[0]}[$T_NAME]);
-		    $canon =~ s+_so$++;
-		    return "\$(${canon}_CXX_SRCS)";
-		  });
-    if (!$no_extra) {
-      generate_list("",1,[ "\$(EXTRA_CXX_SRCS)" ]);
-    }
-    generate_list("RC_SRCS",$no_extra,@$project[$P_TARGETS],sub
-		  {
-		    my $canon=canonize(@{$_[0]}[$T_NAME]);
-		    $canon =~ s+_so$++;
-		    return "\$(${canon}_RC_SRCS)";
-		  });
-    if (!$no_extra) {
-      generate_list("",1,[ "\$(EXTRA_RC_SRCS)" ]);
-    }
-  }
-  print FILEO "\n\n";
-  print FILEO "### Tools\n\n";
-  print FILEO "CC = winegcc\n";
-  print FILEO "CXX = wineg++\n";
-  print FILEO "RC = wrc\n";
-  print FILEO "\n\n";
+      my $all_src=[@{@$target[$T_SOURCES_C]}, @{@$target[$T_SOURCES_CXX]}, @{@$target[$T_SOURCES_RC]}];
 
-  print FILEO "### Generic targets\n\n";
-  print FILEO "all:";
-  if (@$project[$P_PATH] eq "") {
-    print FILEO " \$(SUBDIRS)";
-  }
-  if (@{@$project[$P_TARGETS]} > 0) {
-    print FILEO " \$(DLLS:%=%.so) \$(EXES:%=%.so)";
-  }
-  print FILEO "\n\n";
-  print FILEO "### Build rules\n";
-  print FILEO "\n";
-  print FILEO ".PHONY: all clean dummy\n";
-  print FILEO "\n";
-  print FILEO "\$(SUBDIRS): dummy\n";
-  print FILEO "\t\@cd \$\@ && \$(MAKE)\n";
-  print FILEO "\n";
-  print FILEO "# Implicit rules\n";
-  print FILEO "\n";
-  print FILEO ".SUFFIXES: .cpp .rc .res\n";
-  print FILEO "DEFINCL = \$(INCLUDE_PATH) \$(DEFINES) \$(OPTIONS)\n";
-  print FILEO "\n";
-  print FILEO ".c.o:\n";
-  print FILEO "\t\$(CC) -c \$(CFLAGS) \$(CEXTRA) \$(DEFINCL) -o \$\@ \$<\n";
-  print FILEO "\n";
-  print FILEO ".cpp.o:\n";
-  print FILEO "\t\$(CXX) -c \$(CXXFLAGS) \$(CXXEXTRA) \$(DEFINCL) -o \$\@ \$<\n";
-  print FILEO "\n";
-  print FILEO ".cxx.o:\n";
-  print FILEO "\t\$(CXX) -c \$(CXXFLAGS) \$(CXXEXTRA) \$(DEFINCL) -o \$\@ \$<\n";
-  print FILEO "\n";
-  print FILEO ".rc.res:\n";
-  print FILEO "\t\$(RC) \$(RCFLAGS) \$(RCEXTRA) \$(DEFINCL) -fo\$@ \$<\n";
-  print FILEO "\n";
-  print FILEO "# Rules for cleaning\n";
-  print FILEO "\n";
-  print FILEO "CLEAN_FILES     = y.tab.c y.tab.h lex.yy.c core *.orig *.rej \\\n";
-  print FILEO "                  \\\\\\#*\\\\\\# *~ *% .\\\\\\#*\n";
-  print FILEO "\n";
-  print FILEO "clean:: \$(SUBDIRS:%=%/__clean__) \$(EXTRASUBDIRS:%=%/__clean__)\n";
-  print FILEO "\t\$(RM) \$(CLEAN_FILES) \$(RC_SRCS:.rc=.res) \$(C_SRCS:.c=.o) \$(CXX_SRCS:.cpp=.o)\n";
-  print FILEO "\t\$(RM) \$(DLLS:%=%.so) \$(EXES:%=%.so) \$(EXES:%.exe=%)\n";
-  print FILEO "\n";
-  print FILEO "\$(SUBDIRS:%=%/__clean__): dummy\n";
-  print FILEO "\tcd `dirname \$\@` && \$(MAKE) clean\n";
-  print FILEO "\n";
-  print FILEO "\$(EXTRASUBDIRS:%=%/__clean__): dummy\n";
-  print FILEO "\t-cd `dirname \$\@` && \$(RM) \$(CLEAN_FILES)\n";
-  print FILEO "\n";
+      # insert spec file for .dll targets
+      if (@$target[$T_TYPE] == $TT_DLL) {
+          my $basename=@$target[$T_NAME];
+          $basename=~ s/\.(dll|exe)$//i;
+          push @$all_src, "$basename.spec";
+      }
 
-  if (@{@$project[$P_TARGETS]} > 0) {
-    print FILEO "### Target specific build rules\n";
-    print FILEO "DEFLIB = \$(LIBRARY_PATH) \$(LIBRARIES) \$(DLL_PATH)\n\n";
-    foreach my $target (@{@$project[$P_TARGETS]}) {
-      my $canon=canonize("@$target[$T_NAME]");
-      $canon =~ s/_so$//;
+      generate_list("${canon}_SRC",1,[@$all_src]);
+      print FILEO "\n";
 
-      print FILEO "\$(${canon}_MODULE).so: \$(${canon}_OBJS)\n";
-      if (@{@$target[$T_SOURCES_CXX]} > 0 or @{@$project_settings[$T_SOURCES_CXX]} > 0) {
-        print FILEO "\t\$(CXX)";
-      } else {
-        print FILEO "\t\$(CC)";
-      }
-      print FILEO " \$(${canon}_LDFLAGS) -o \$\@ \$(${canon}_OBJS) \$(${canon}_LIBRARY_PATH) \$(DEFLIB) \$(${canon}_DLLS:%=-l%) \$(${canon}_LIBRARIES:%=-l%)\n";
-      print FILEO "\n\n";
+      generate_list("@$target[$T_NAME]:\tLDFLAGS",1,@$target[$T_LDFLAGS]);
+      generate_list("@$target[$T_NAME]:\tDLL_PATH",1,@$target[$T_DLL_PATH]);
+      generate_list("@$target[$T_NAME]:\tDLLS",1,@$target[$T_DLLS]);
+      generate_list("@$target[$T_NAME]:\tLIBRARY_PATH",1,@$target[$T_LIBRARY_PATH]);
+      generate_list("@$target[$T_NAME]:\tLIBS",1,@$target[$T_LIBRARIES]);
+
+      print FILEO "\n\n\n";
     }
   }
+  print FILEO "\n\n";
+  print FILEO "# Include rules\n";
+  print FILEO "#\n";
+  print FILEO "# if located in non-std place, set in your environment\n";
+  print FILEO '# MAKEFLAGS="-I /path/to/winemake-include-dir/"',"\n";
+  print FILEO "#\n";
+  print FILEO "# or put Winemake.include at the root of your project.\n";
+  print FILEO "# or include Winemake.include in the top-level Makefile with explicit path.\n";
+  print FILEO "#\n";
+  print FILEO "# NB: std-places (as stated in GNU make manual):\n";
+  print FILEO "#     /usr/include  /usr/local/include ...\n";
+  print FILEO "include Winemake.include";
   close(FILEO);
 
 }
-- 
1.4.4.4

-------------- next part --------------
A non-text attachment was scrubbed...
Name: winelib-gnu-make.tar.gz
Type: application/x-tgz
Size: 21289 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-devel/attachments/20070902/4f06e34d/winelib-gnu-make.tar-0001.bin


More information about the wine-devel mailing list