>From 0d19d4bd95a97dc7d582872f22f4b393521709f8 Mon Sep 17 00:00:00 2001 From: Kirill Smelkov 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 + + +# 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,$*) +@C = $(call canonicalize,$@) + +# handy variables +1C_SRC = $($(1C)_SRC) +@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),@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