]> rtime.felk.cvut.cz Git - omk.git/commitdiff
Merge branch 'master' into devel devel
authorMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 19 Feb 2009 08:25:56 +0000 (09:25 +0100)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 19 Feb 2009 08:25:56 +0000 (09:25 +0100)
Conflicts:
snippets/include.omk
snippets/qt.omk

17 files changed:
devel-test/Makefile [new file with mode: 0644]
devel-test/Makefile.build [new file with mode: 0644]
devel-test/Makefile.omk [new file with mode: 0644]
devel-test/Makefile.rules [new symlink]
devel-test/config.omk-default [new file with mode: 0644]
devel-test/dir/Makefile [new file with mode: 0644]
devel-test/dir/Makefile.omk [new file with mode: 0644]
devel-test/dir/test.c [new file with mode: 0644]
omk-alias.sh [new file with mode: 0644]
snippets/Makefile.rules.test [new file with mode: 0644]
snippets/base.omk
snippets/build.omk [new file with mode: 0644]
snippets/config_h.omk
snippets/cprog.omk [new file with mode: 0644]
snippets/include.omk
snippets/prepare.omk [new file with mode: 0644]
snippets/qt.omk

diff --git a/devel-test/Makefile b/devel-test/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/devel-test/Makefile.build b/devel-test/Makefile.build
new file mode 100644 (file)
index 0000000..f616dd2
--- /dev/null
@@ -0,0 +1,27 @@
+QUIET_CMD_ECHO = echo
+#####################
+# Build pseudo-pass #
+#####################
+
+all: build-pseudo-pass
+
+rule_targets = $($(1)_targets)
+rule_deps    = $($(1)_deps)
+rule_msg     = $($(1)_msg)
+rule_cmd     = $($(1)_cmd)
+
+# Usage: $(call build_rule,<target>)
+define build_rule
+$(value rule_targets): $(value rule_deps) $(omk_inc_file)
+       @$(QUIET_CMD_ECHO) "  "$(rule_msg) "$$@" #"$$(call strip_out,$$@)"
+       $(Q)$(value rule_cmd)
+endef
+
+# TODO: Include target.omk only in the subtree
+-include $(shell true; find $(USER_BUILD_DIR) -name '*omk.inc') # `true' is a hack for MinGW
+
+$(foreach rule,$(prepared_rules),$(eval $(call build_rule,$(rule))))
+
+.PHONY: build-pseudo-pass
+build-pseudo-pass: $(foreach target,$(omk_goals),$(target))
+
diff --git a/devel-test/Makefile.omk b/devel-test/Makefile.omk
new file mode 100644 (file)
index 0000000..87e8848
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS=dir
diff --git a/devel-test/Makefile.rules b/devel-test/Makefile.rules
new file mode 120000 (symlink)
index 0000000..785ab99
--- /dev/null
@@ -0,0 +1 @@
+../snippets/Makefile.rules.test
\ No newline at end of file
diff --git a/devel-test/config.omk-default b/devel-test/config.omk-default
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/devel-test/dir/Makefile b/devel-test/dir/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/devel-test/dir/Makefile.omk b/devel-test/dir/Makefile.omk
new file mode 100644 (file)
index 0000000..13d3ec5
--- /dev/null
@@ -0,0 +1,4 @@
+bin_PROGRAMS = test
+
+test_SOURCES = test.c
+test_LIBS = m
diff --git a/devel-test/dir/test.c b/devel-test/dir/test.c
new file mode 100644 (file)
index 0000000..822e084
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main()
+{
+        printf("Hello world\n");
+        return 0;
+}
diff --git a/omk-alias.sh b/omk-alias.sh
new file mode 100644 (file)
index 0000000..c525a20
--- /dev/null
@@ -0,0 +1 @@
+alias omk='_omk_rules=$(old_pwd=""; while [ ! -e Makefile.rules ]; do if [ "$old_pwd" = `pwd`  ]; then echo "Makefile.rules has not been found in this or parent directory" >&2; exit 1; else old_pwd=`pwd`; cd -L .. 2>/dev/null; fi; done; echo `pwd`/Makefile.rules); [ "$_omk_rules" ] && make -f $_omk_rules'
diff --git a/snippets/Makefile.rules.test b/snippets/Makefile.rules.test
new file mode 100644 (file)
index 0000000..1f819a0
--- /dev/null
@@ -0,0 +1,139 @@
+
+# -*- makefile-gmake -*-
+include base.omk #omkbuild
+
+USER_INCLUDE_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/include
+USER_LIB_DIR     := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/lib
+USER_UTILS_DIR   := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin-utils
+USER_TESTS_DIR   := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin-tests
+USER_BIN_DIR     := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin
+USER_BUILD_DIR   := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/user
+#LINK_BUILD_DIR   := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/link
+
+check-dir::
+       @$(call mkdir_def,$(USER_BUILD_DIR))
+       @$(call mkdir_def,$(USER_INCLUDE_DIR))
+       @$(call mkdir_def,$(USER_LIB_DIR))
+       @$(call mkdir_def,$(USER_BIN_DIR))
+       @$(call mkdir_def,$(USER_UTILS_DIR))
+       @$(call mkdir_def,$(USER_TESTS_DIR))
+
+# Avoid double slash at the end in the top-level directory
+USER_OBJS_DIR = $(USER_BUILD_DIR)$(RELATIVE_DIR:%=/%)
+KERN_OBJS_DIR = $(KERN_BUILD_DIR)$(RELATIVE_DIR:%=/%)
+
+############
+# Programs #
+############
+
+ifeq ($(BUILD_OS),)
+  # Check for target
+  ifeq ($(OS),Windows_NT)
+    BUILD_OS := win32
+  else
+    BUILD_OS := $(shell uname | tr '[A-Z]' '[a-z]' )
+    #$(warning BUILD_OS=$(BUILD_OS))
+  endif
+endif
+
+ifeq ($(TARGET_OS),)
+  TARGET_OS := $(BUILD_OS)
+endif
+
+export TARGET_OS
+export BUILD_OS
+
+# Assign default values to CFLAGS variable. If the variable is defined
+# earlier (i.g. in config.omk), it is not overriden here.
+CFLAGS ?= -O2 -Wall
+CXXFLAGS ?= -O2 -Wall
+
+
+CPPFLAGS  += -I $(USER_INCLUDE_DIR)
+LOADLIBES += -L$(USER_LIB_DIR) 
+LOADLIBES += $(lib_LOADLIBES:%=-l%)
+
+LIB_CPPFLAGS += $(CPPFLAGS)
+LIB_CFLAGS   += $(CFLAGS)
+
+ifeq ($(TARGET_OS),win32)
+  SOLIB_EXT = dll
+else
+  SOLIB_EXT = so
+  SOLIB_PICFLAGS += -fpic
+endif
+
+# Check GCC version for user build
+ifndef CC_MAJOR_VERSION
+CC_MAJOR_VERSION := $(shell $(CC) -dumpversion | sed -e 's/\([^.]\)\..*/\1/')
+# TODO: export CC_MAJOR_VERSION to save the above shell invocation in
+# submakes. This will work only if CC is not changed in Makefile.omk.
+endif
+# Prepare suitable define for dependency building
+ifeq ($(CC_MAJOR_VERSION),2)
+CC_DEPFLAGS = -Wp,-MD,"$$@.d.tmp"
+else
+CC_DEPFLAGS = -MT $$@ -MD -MP -MF "$$@.d.tmp"
+endif
+
+c_o_COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -DOMK_FOR_USER
+
+cc_o_COMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -DOMK_FOR_USER
+
+S_o_COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) $(ASFLAGS) -DOMK_FOR_USER
+
+c_o_cmd = \
+       if $(c_o_COMPILE) $(CC_DEPFLAGS) -o $$@ -c $$< ; \
+       then mv -f "$$@.d.tmp" "$$@.d"; \
+       else rm -f "$$@.d.tmp"; exit 1; \
+       fi
+
+cc_o_cmd = \
+       if $(cc_o_COMPILE) $(CC_DEPFLAGS) -o $$@ -c $$< ; \
+       then mv -f "$$@.d.tmp" "$$@.d"; \
+       else rm -f "$$@.d.tmp"; exit 1; \
+       fi
+
+S_o_cmd = \
+       if $(S_o_COMPILE) -D__ASSEMBLY__ $(CC_DEPFLAGS) $($(1)_CFLAGS) -o $$@ -c $$< ; \
+       then mv -f "$$@.d.tmp" "$$@.d" ; \
+       else rm -f "$$@.d.tmp" ; exit 1; \
+       fi
+# TODO: Implement $($(1)_CFLAGS)
+
+# Default values for IDL_* variable are suitable for ORBit-like IDL compilers
+IDL_CLIENT_SOURCES ?= $(1:%.idl=%-stubs.c) $(1:%.idl=%-common.c)
+IDL_SERVER_SOURCES ?= $(1:%.idl=%-skels.c) $(1:%.idl=%-common.c)
+IDL_TARGETS ?= $(1:%.idl=%-stubs.c) $(1:%.idl=%-skels.c) $(1:%.idl=%-common.c) $(1:%.idl=%.h)
+IDL_FLAGS ?= --output-dir=$(USER_OBJS_DIR)
+
+idl_src_cmd = $(IDL_COMPILER) $(IDL_FLAGS) $($(1)_IDLFLAGS) $$<
+
+# TODO: Implement CMETRIC
+
+_linker = $(if $(call c++sources,$($(1)_SOURCES) $($(1)_GEN_SOURCES)),$(CXX),$(CC))
+_map_file = $(USER_OBJS_DIR)/$(1).exe.map
+_dep_file = $(USER_OBJS_DIR)/$(1).exe.d
+program_cmd = set -e; \
+       $(_linker) $($(1)_OBJS) $($(1)_LIBS:%=-l%) $(LOADLIBES) $(LDFLAGS) \
+               -Wl,-rpath-link,$(USER_LIB_DIR) -Wl,-Map,$(_map_file) -o $$@; \
+       echo "$$@: \\" >$(_dep_file); \
+       sed -n -e 's|^LOAD \(.*\)$$$$|  \1  \&|p' $(_map_file)\
+       |tr '&' '\134' >>$(_dep_file); \
+       echo >>$(_dep_file)
+
+library_cmd = $(AR) rcs $$@ $$^
+
+solib_cmd = set -e; \
+       $(_linker) $($(1)_OBJS) $($(1)_LIBS:%=-l%) $(LOADLIBES) $(LDFLAGS) \
+               -Wl,-rpath-link,$(USER_LIB_DIR) -Wl,-Map,$(_map_file) -o $$@; \
+       echo "$$@: \\" >$(_dep_file); \
+       sed -n -e 's|^LOAD \(.*\)$$$$|  \1  \&|p' $(_map_file)\
+       |tr '&' '\134' >>$(_dep_file); \
+       echo >>$(_dep_file)
+
+
+include cprog.omk #omkbuild
index f0f7a88194bb957c79e3f892bd146e118d2bde9b..da68ea537b393b743ea8cd1716768a9128f6b6b9 100644 (file)
@@ -34,8 +34,6 @@ ifndef OUTPUT_DIR
 OUTPUT_DIR := $(MAKERULES_DIR)
 endif
 
-.PHONY: all default check-make-ver omkize
-
 ifdef W
   ifeq ("$(origin W)", "command line")
     OMK_WHOLE_TREE:=$(W)
@@ -46,14 +44,27 @@ ifndef OMK_WHOLE_TREE
 endif
 
 ifneq ($(OMK_WHOLE_TREE),1)
-all: check-make-ver default
-       @echo "Compilation finished"
+  ifndef omk_prereq_checked
+  omk_checks=check-make-ver check-dir
+  export omk_prereq_checked=1
+  endif
+all: build-pseudo-pass
+
+prepare: $(omk_checks) prepare-pass
+build-pseudo-pass: prepare
+       +@$(QUIET_CMD_ECHO) "make[omk]: build"
+       $(Q3)$(MAKE) -C $(MAKERULES_DIR) -f Makefile.rules build
+       @$(QUIET_CMD_ECHO) "Compilation finished"
+
+prepare-pass:: $(omk_checks)
 else
 # Run make in the top-level directory
 all:
-       @$(MAKE) -C $(MAKERULES_DIR) OMK_SERIALIZE_INCLUDED=n SOURCES_DIR=$(MAKERULES_DIR) RELATIVE_DIR="" $(MAKECMDGOALS) W=0
+       $(Q3)$(MAKE) -C $(MAKERULES_DIR) OMK_SERIALIZE_INCLUDED=n SOURCES_DIR=$(MAKERULES_DIR) RELATIVE_DIR="" $(MAKECMDGOALS) W=0
 endif
 
+.PHONY: all default check-make-ver omkize prepare build-pseudo-pass
+
 ifdef OMK_TESTSROOT
 # Usage: $(call canttest,<error message>)
 define canttest
@@ -134,11 +145,11 @@ endif
 ifndef OMK_VERBOSE
   OMK_VERBOSE = 0
 endif
-ifneq ($(OMK_VERBOSE),0)
-  Q =
-else
-  Q = @
-endif
+
+Q =  $(if $(filter 0    ,$(OMK_VERBOSE)),@)
+Q2 = $(if $(filter 0 1  ,$(OMK_VERBOSE)),@)
+Q3 = $(if $(filter 0 1 2,$(OMK_VERBOSE)),@)
+
 ifneq ($(findstring s,$(MAKEFLAGS)),)
   QUIET_CMD_ECHO = true
   OMK_SILENT = 1
@@ -146,6 +157,25 @@ else
   QUIET_CMD_ECHO = echo
 endif
 
+# Convenient variables
+comma   := ,
+squote  := '
+#'
+empty   :=
+space   := $(empty) $(empty)
+
+###
+# Escape single quote for use in echo statements
+escsq = $(subst $(squote),'\$(squote)',$1)
+
+###
+# Strip/replace OUTPUT_DIR from/in the argument
+strip_out = $(patsubst $(OUTPUT_DIR)/%,%,$(1))
+repl_out  = $(patsubst $(OUTPUT_DIR)/%,$$(OUTPUT_DIR)/%,$(1))
+
+.PHONY: FORCE
+
+
 MAKEFILE_OMK=Makefile.omk
 # All subdirectories (even linked ones) containing Makefile.omk
 # Usage in Makefile.omk: SUBDIRS = $(ALL_OMK_SUBDIRS)
@@ -162,6 +192,7 @@ endif
 OMK_INCLUDED := 1
 endif
 
+
 check-make-ver:
        @GOOD_MAKE_VERSION=`echo $(MAKE_VERSION) | sed -n -e 's/^[4-9]\..*\|^3\.9[0-9].*\|^3\.8[1-9].*/y/p'` ; \
        if [ x$$GOOD_MAKE_VERSION != xy ] ; then \
@@ -171,12 +202,12 @@ check-make-ver:
 
 distclean dist-clean:
        @$(QUIET_CMD_ECHO) "  RM      $(COMPILED_DIR_NAME) $(BUILD_DIR_NAME)"
-       @rm -fr $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)  $(OUTPUT_DIR)/$(BUILD_DIR_NAME)
+       $(Q3)rm -fr $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)  $(OUTPUT_DIR)/$(BUILD_DIR_NAME)
 
 # Common OMK templates
 # ====================
 
-# Syntax: $(call mkdir,<dir name>)
+# Syntax: $(call mkdir_def,<dir name>)
 define mkdir_def
        [ -d $(1) ] || mkdir -p $(1) || exit 1
 endef
@@ -194,20 +225,26 @@ SUBDIR_MAKEFILE=$(SOURCES_DIR)/$(3)/Makefile
 SOURCESDIR_MAKEFILE=$(SOURCES_DIR)/Makefile
 endif
 
+BUILD_DIR_NAME = _build
+COMPILED_DIR_NAME = _compiled
+
+BUILD_OMK_DIR := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/omk
+OMK_WORK_DIR := $(BUILD_OMK_DIR)$(RELATIVE_DIR:%=/%)
+
+check-dir::
+       $(Q3)$(call mkdir_def,$(BUILD_OMK_DIR))
+
 pass = $(strip $(1))
 
 # Call a pass in a subdirectory
-# Usage: $(call omk_pass_subdir_template,<pass name>,<build dir>,<subdir>)
+# Usage: $(call omk_pass_subdir_template,<pass name>,<subdir>)
 define omk_pass_subdir_template
-.PHONY: $(pass)-$(3)-subdir
-$(pass)-submakes: $(pass)-$(3)-subdir
-$(pass)-$(3)-subdir:
-       @$(call mkdir_def,$(2)/$(3))
-       +@$(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(3) $(NO_PRINT_DIRECTORY) \
-               RELATIVE_DIR=$(RELATIVE_PREFIX)$(3) -C $(2)/$(3) \
-               -f $(SUBDIR_MAKEFILE) $(pass)-submakes
-# In subdirectories we can call submakes directly since passes are
-# already searialized on the toplevel make.
+.PHONY: $(pass)-$(2)-subdir
+$(pass)-subdirs: $(pass)-$(2)-subdir
+$(pass)-$(2)-subdir:
+       +$(Q3)$(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(2) $(NO_PRINT_DIRECTORY) \
+               RELATIVE_DIR=$(RELATIVE_PREFIX)$(2) -C $(2) \
+               -f $(SUBDIR_MAKEFILE) $(pass)
 endef
 
 ifdef OMK_TESTSROOT
@@ -219,57 +256,48 @@ endif
 define extra_rules_subdir_template
 extra-rules-subdirs: extra-rules-$(1)
 extra-rules-$(1):
-       +@$(MAKE) OMK_SERIALIZE_INCLUDED=n MAKERULES_DIR=$(SOURCES_DIR)/$(1) OUTPUT_DIR=$(OUTPUT_DIR) \
+       +$(Q3)$(MAKE) OMK_SERIALIZE_INCLUDED=n MAKERULES_DIR=$(SOURCES_DIR)/$(1) OUTPUT_DIR=$(OUTPUT_DIR) \
                SOURCES_DIR=$(SOURCES_DIR)/$(1) RELATIVE_DIR=$(RELATIVE_PREFIX)$(1) -C $(SOURCES_DIR)/$(1)
 endef
 
-.PHONY: extra-rules-subdirs
+.PHONY: extra-rules-subdirs mkdir-omk-work
 extra-rules-subdirs:
 
 $(foreach subdir,$(EXTRA_RULES_SUBDIRS),$(eval $(call extra_rules_subdir_template,$(subdir))))
 
-# Usage: $(call omk_pass_template,<pass name>,<build dir>,[<local make flags>],[<local enable condition>])
+# Usage: $(call omk_pass_template,<pass name>)
 define omk_pass_template
-.PHONY: $(pass) $(pass)-local $(pass)-check $(pass)-submakes
-$(foreach subdir,$(SUBDIRS),$(eval $(call omk_pass_subdir_template,$(pass),$(2),$(subdir))))
-$(pass):
-# Submakes have to be called this way and not as dependecies for pass
-# serialization to work
-       +@$(MAKE) SOURCES_DIR=$(SOURCES_DIR) $(NO_PRINT_DIRECTORY) \
-               RELATIVE_DIR=$(RELATIVE_DIR) \
-               -f $(SOURCESDIR_MAKEFILE) $(pass)-submakes
-$(pass)-submakes:
-       @true                   # Do not emit "nothing to be done" messages
-
-ifneq ($(4)$($(pass)_HOOKS),)
-$(pass)-submakes: $(pass)-this-dir
-$(pass)-this-dir: $(foreach subdir,$(SUBDIRS),$(pass)-$(subdir)-subdir)
-       +@echo "make[omk]: $(pass) in $(RELATIVE_DIR)"
-       @$(call mkdir_def,$(2))
-       +@$(MAKE) $(NO_PRINT_DIRECTORY) SOURCES_DIR=$(SOURCES_DIR) RELATIVE_DIR=$(RELATIVE_DIR) -C $(2) \
-               -f $(SOURCESDIR_MAKEFILE) $(3) $(check-target) $(1:%=%-local)
-$(pass)-local: $($(pass)_HOOKS)
-endif
+.PHONY: $(pass) $(pass)-msg $(pass)-subdirs
+$(pass):: $(pass)-subdirs $(pass)-msg mkdir-omk-work
+$(foreach subdir,$(SUBDIRS),$$(eval $$(call omk_pass_subdir_template,$(pass),$(subdir))))
+
+$(pass)-msg: $(pass)-subdirs
+       +@$(QUIET_CMD_ECHO) "make[omk]: $(pass) in $(RELATIVE_DIR)"
 endef
 
+mkdir-omk-work:
+       $(Q3)$(call mkdir_def,$(OMK_WORK_DIR))
+
+
+
 # =======================
 # DEFAULT CONFIG PASS
 
 default-config:
-       @echo "# Start of OMK config file" > "$(CONFIG_FILE)-default"
-       @echo "# This file should not be altered manually" >> "$(CONFIG_FILE)-default"
-       @echo "# Overrides should be stored in file $(notdir $(CONFIG_FILE))" >> "$(CONFIG_FILE)-default"
-       @echo >> "$(CONFIG_FILE)-default"
-       @$(MAKE) $(NO_PRINT_DIRECTORY) -C $(OUTPUT_DIR) \
+       $(Q3)echo "# Start of OMK config file" > "$(CONFIG_FILE)-default"
+       $(Q3)echo "# This file should not be altered manually" >> "$(CONFIG_FILE)-default"
+       $(Q3)echo "# Overrides should be stored in file $(notdir $(CONFIG_FILE))" >> "$(CONFIG_FILE)-default"
+       $(Q3)echo >> "$(CONFIG_FILE)-default"
+       $(Q3)$(MAKE) $(NO_PRINT_DIRECTORY) -C $(MAKERULES_DIR) \
                RELATIVE_DIR="" SOURCES_DIR=$(OUTPUT_DIR) \
                -f $(OUTPUT_DIR)/Makefile default-config-pass
 
 $(eval $(call omk_pass_template,default-config-pass,$$(LOCAL_BUILD_DIR),,always))
 
-default-config-pass-local:
-#      @echo Default config for $(RELATIVE_DIR)
-       @echo "# Config for $(RELATIVE_DIR)" >> "$(CONFIG_FILE)-default"
-       @$(foreach x, $(default_CONFIG), echo '$(x)' | \
+default-config-pass::
+#      $(Q3)echo Default config for $(RELATIVE_DIR)
+       $(Q3)echo "# Config for $(RELATIVE_DIR)" >> "$(CONFIG_FILE)-default"
+       $(Q3)$(foreach x, $(default_CONFIG), echo '$(x)' | \
                sed -e 's/^[^=]*=x$$/#\0/' >> "$(CONFIG_FILE)-default" ; )
 
 
@@ -284,3 +312,6 @@ omkize:
              cp -v Makefile "$${d}/Makefile"; \
           fi \
        done
+
+include prepare.omk #omkbuild
+include build.omk #omkbuild
diff --git a/snippets/build.omk b/snippets/build.omk
new file mode 100644 (file)
index 0000000..165f715
--- /dev/null
@@ -0,0 +1,37 @@
+
+#####################
+# Build pseudo-pass #
+#####################
+
+ifneq (,$(filter build,$(MAKECMDGOALS)))
+rule_targets = $(value $(1)_targets)
+rule_deps    = $(value $(1)_deps)
+rule_msg     = $(value $(1)_msg)
+rule_cmd     = $(value $(1)_cmd)
+
+# Usage: $(eval $(call build_rule,<target>))
+define build_rule
+$(rule_targets): $(rule_deps) #$(omk_inc_file)
+       @$(QUIET_CMD_ECHO) "  "$(rule_msg)"$$@" #"$$(call strip_out,$$@)"
+       $(Q)$(rule_cmd)
+endef
+
+# Goals are included only for this directory and all subdirectories
+# TODO: What if a target depends on a library from different
+# subtree. Then the library would be remade even if it should not
+# because its __goals.omk.inc is not included.
+-include $(shell true; find $(OMK_WORK_DIR) -name '__goals.omk.inc') # `true' is a hack for MinGW
+
+# Definition of rules is included everywhere to allow multi-directory
+# targets. 
+-include $(shell true; find $(BUILD_OMK_DIR) -name '*.omk.inc' -not -name '__goals.omk.inc') # `true' is a hack for MinGW
+
+# FIXME: Disable automatic remake of included files
+
+$(foreach rule,$(prepared_rules),$(eval $(call build_rule,$(rule))))
+
+.PHONY: build
+
+build: $(omk_goals)
+
+endif # (,$(filter build,$(MAKECMDGOALS)))
index 9718d85b0d4cb4c3477c7f331191be11a30ea4c9..bbfe0b2dba39b41e32c09b7fb3d9aa819fd6e9cb 100644 (file)
@@ -53,7 +53,7 @@ _$(basename $(notdir $(confh)))_H \
 config_h_stamp_files = $(addprefix $(USER_OBJS_DIR)/,$(notdir $(addsuffix .stamp,$(config_include_HEADERS) $(LOCAL_CONFIG_H))))
 
 # Add some hooks to standard passes
-include-pass-local: $(config_h_stamp_files)
+include-pass-local: $(config_h_stamp_files) # TODO remove -local
 
 ifneq ($(KERN_CONFIG_HEADERS_REQUIRED),)
 
@@ -68,11 +68,11 @@ _$(basename $(notdir $(confh)))_H \
 kern_config_h_stamp_files = $(addprefix $(KERN_OBJS_DIR)/,$(notdir $(addsuffix .stamp,$(config_include_HEADERS) $(LOCAL_CONFIG_H))))
 
 # Add some hooks to standard passes
-include-pass-local: $(kern_config_h_stamp_files)
+include-pass-local: $(kern_config_h_stamp_files) # TODO remove -local
 
 endif
 
-clean-local: clean-local-config-h
+clean-local: clean-local-config-h # TODO remove -local
 
 clean-local-config-h:
        @$(foreach confh,$(config_h_stamp_files) $(kern_config_h_stamp_files),\
diff --git a/snippets/cprog.omk b/snippets/cprog.omk
new file mode 100644 (file)
index 0000000..29420db
--- /dev/null
@@ -0,0 +1,98 @@
+
+##################
+# C/C++ programs #
+##################
+
+c++ext = cc C cxx cpp
+c++sources = $(strip $(foreach ext,$(c++ext),$(filter %.$(ext),$(1))))
+
+###
+# template_variables - variables common to program, libraries, ...
+#
+define template_variables
+USER_IDLS  += $$($(1)_SERVER_IDL) $$($(1)_CLIENT_IDL) $$($(1)_IDL)
+$(1)_GEN_SOURCES += $$(call IDL_SERVER_SOURCES,$$($(1)_SERVER_IDL))
+$(1)_GEN_SOURCES += $$(call IDL_CLIENT_SOURCES,$$($(1)_CLIENT_IDL))
+$(1)_GEN_SOURCES += $$(sort $$(call IDL_SERVER_SOURCES,$$($(1)_IDL)) \
+                           $$(call IDL_CLIENT_SOURCES,$$($(1)_IDL)))
+USER_GEN_SOURCES += $$($(1)_GEN_SOURCES)
+$(1)_OBJS += $(foreach ext,c $(c++ext),$$(patsubst %.$(ext),%.o,$$(filter %.$(ext),$$($(1)_SOURCES) $$($(1)_GEN_SOURCES))))
+$(1)_OBJS := $$(sort $$($(1)_OBJS:%/=%)) # Why is here the backslash substitution???
+$(1)_OBJS := $$(addprefix $(USER_OBJS_DIR)/,$$(sort $$($(1)_OBJS:%/=%)))
+
+USER_OBJS  += $$($(1)_OBJS)
+USER_SOURCES += $$($(1)_SOURCES)
+endef
+
+###
+# program_template
+#
+# Usage: $(call program_template,<executable-name>,<bin|utils|test>)
+define program_template
+$(template_variables)
+$$(eval $$(call prepare_rule_goal,\
+       $(USER_BIN_DIR)/$(1)$(EXE_SUFFIX),\
+       $$($(1)_OBJS),\
+       "LINK    ",\
+       $$(call program_cmd,$(1))))
+endef
+
+###
+# library_template
+#
+# Usage: $(call library_template,<library-name>)
+define library_template
+$(template_variables)
+$$(eval $$(call prepare_rule_goal,\
+       $(USER_LIB_DIR)/lib$(1).a,\
+       $$($(1)_OBJS),\
+       "AR      ",\
+       $$(call library_cmd,$(1))))
+endef
+
+###
+# solib_template
+#
+# Usage: $(call solib_template,<library-name>)
+define solib_template
+$(template_variables) # FIXME: OBJSLO, etc.
+# TODO: Add dependencies on other shared libraries ala:
+# $(1)_libs += $$($(1)_LIBS) $$(lib_LOADLIBES)
+# $(1)_shared_libs = $$(patsubst %,$(USER_LIB_DIR)/lib%.$(SOLIB_EXT),$$(filter $$(shared_libs),$$($(1)_libs)))
+
+$$(eval $$(call prepare_rule_goal,\
+       $(USER_LIB_DIR)/lib$(1).$(SOLIB_EXT),\
+       $$($(1)_OBJS),\
+       "LINK    ",\
+       $$(call solib_cmd,$(1))))
+endef
+
+ifneq ($(bin_PROGRAMS)$(test_PROGRAMS)$(utils_PROGRAMS)$(lib_LIBRARIES)$(shared_LIBRARIES),)
+prepare-pass::
+       @$(call mkdir_def,$(USER_OBJS_DIR))
+endif
+
+# TODO: $(foreach cmetrh,...)
+
+$(foreach prog,$(bin_PROGRAMS),$(eval $(call program_template,$(prog),bin)))
+$(foreach prog,$(utils_PROGRAMS),$(eval $(call program_template,$(prog),utils)))
+$(foreach prog,$(test_PROGRAMS),$(eval $(call program_template,$(prog),test)))
+$(foreach lib,$(lib_LIBRARIES),$(eval $(call library_template,$(lib))))
+$(foreach lib,$(shared_LIBRARIES),$(eval $(call solib_template,$(lib))))
+
+$(foreach src,$(filter %.c,$(USER_SOURCES)),\
+       $(eval $(call prepare_rule,\
+               $(USER_OBJS_DIR)/$(src:%.c=%.o),\
+               $(SOURCES_DIR)/$(src),\
+               "CC      ",\
+               $(c_o_cmd))))
+
+include include.omk #omkbuild
+$(eval $(call include-pass-template,$(USER_INCLUDE_DIR),include))
+
+$(foreach idl,$(USER_IDLS),\
+       $(eval $(call prepare_rule_goal,\
+               $(addprefix $(USER_OBJS_DIR)/,$(call IDL_TARGETS,$(idl))),\
+               $(SOURCES_DIR)/$(idl),\
+               "IDL     ",\
+               $(call idl_src_cmd,$(idl)))))
index 05978789cf2cefd1eed58950a6bd581844c68c33..b5ed4906923c78b4014ec676922c774f9533c856 100644 (file)
@@ -1,5 +1,5 @@
 # LN_HEADERS       .. if "y", header files are symbolicaly linked instead of copied.
-ifeq ($(OMK_VERBOSE),1)
+ifneq ($(OMK_VERBOSE),0)
 CPHEADER_FLAGS += -v
 LNHEADER_FLAGS += -v
 endif
@@ -10,7 +10,7 @@ define cp_cmd
 endef
 else
 define cp_cmd
-( echo "  LN      $(1:$(OUTPUT_DIR)/%=%) -> $(2:$(OUTPUT_DIR)/%=%)"; [ -f $(1) ] && ln -sf $(LNHEADER_FLAGS) $(1) $(2) )
+( echo "  LN      $(1:$(OUTPUT_DIR)/%=%) -> $(2:$(OUTPUT_DIR)/%=%)"; [ -f $(1) ] || exit 1; ln -sf $(LNHEADER_FLAGS) $(SOURCES_DIR)/$(1) $(2) )
 endef
 endif
 
@@ -19,20 +19,22 @@ endif
 
 # Syntax: $(call include-pass-template,<include dir>,<keyword>)
 define include-pass-template
-include-pass-local: include-pass-local-$(2)
-include-pass-local-$(2): $$($(2)_GEN_HEADERS) $$(foreach f,$$(renamed_$(2)_GEN_HEADERS),$$(shell echo '$$(f)' | sed -e 's/^\(.*\)->.*$$$$/\1/'))
-       @$$(foreach f, $$($(2)_HEADERS), cmp --quiet $$(SOURCES_DIR)/$$(f) $(1)/$$(notdir $$(f)) \
-          || $$(call cp_cmd,$$(SOURCES_DIR)/$$(f),$(1)/$$(notdir $$(f))) || exit 1 ; )
-       @$$(foreach f, $$($(2)_GEN_HEADERS), cmp --quiet $$(f) $(1)/$$(notdir $$(f)) \
-          || $$(call cp_cmd,$$(LOCAL_BUILD_DIR)/$$(f),$(1)/$$(notdir $$(f))) || exit 1 ; ) # FIXME: Use correct build dir, then document it
-       @$$(foreach f, $$(nobase_$(2)_HEADERS), cmp --quiet $$(SOURCES_DIR)/$$(f) $(1)/$$(f) \
-          || ( mkdir -p $(1)/$$(dir $$(f)) && $$(call cp_cmd,$$(SOURCES_DIR)/$$(f),$(1)/$$(f)) ) || exit 1 ; )
-       @$$(foreach f, $$(renamed_$(2)_HEADERS), \
-          srcfname=`echo '$$(f)' | sed -e 's/^\(.*\)->.*$$$$/\1/'` ; destfname=`echo '$$(f)' | sed -e 's/^.*->\(.*\)$$$$/\1/'` ; \
-          cmp --quiet $$(SOURCES_DIR)/$$$${srcfname} $(1)/$$$${destfname} \
-          || ( mkdir -p `dirname $(1)/$$$${destfname}` && $$(call cp_cmd,$$(SOURCES_DIR)/$$$${srcfname},$(1)/$$$${destfname}) ) || exit 1 ; )
-       @$$(foreach f, $$(renamed_$(2)_GEN_HEADERS), \
+prepare-pass::
+       $(Q3)$$(foreach f, $$($(2)_HEADERS), cmp --quiet $$(f) $(1)/$$(notdir $$(f)) \
+          || $$(call cp_cmd,$$(f),$(1)/$$(notdir $$(f))) || exit 1 ; )
+       $(Q3)$$(foreach f, $$($(2)_GEN_HEADERS), cmp --quiet TODO_BUILD_DIR/$$(f) $(1)/$$(notdir $$(f)) \
+          || $$(call cp_cmd,TODO_BUILD_DIR/$$(f),$(1)/$$(notdir $$(f))) || exit 1 ; ) # FIXME: Use correct build dir, then document it
+       $(Q3)$$(foreach f, $$(nobase_$(2)_HEADERS), cmp --quiet $$(f) $(1)/$$(f) \
+          || ( mkdir -p $(1)/$$(dir $$(f)) && $$(call cp_cmd,$$(f),$(1)/$$(f)) ) || exit 1 ; )
+       $(Q3)$$(foreach f, $$(renamed_$(2)_HEADERS), \
           srcfname=`echo '$$(f)' | sed -e 's/^\(.*\)->.*$$$$/\1/'` ; destfname=`echo '$$(f)' | sed -e 's/^.*->\(.*\)$$$$/\1/'` ; \
           cmp --quiet $$$${srcfname} $(1)/$$$${destfname} \
-          || ( mkdir -p `dirname $(1)/$$$${destfname}` && $$(call cp_cmd,$$(LOCAL_BUILD_DIR)/$$$${srcfname},$(1)/$$$${destfname}) ) || exit 1 ; )
+          || ( mkdir -p `dirname $(1)/$$$${destfname}` && $$(call cp_cmd,$$$${srcfname},$(1)/$$$${destfname}) ) || exit 1 ; )
+       $(Q3)$$(foreach f, $$(renamed_$(2)_GEN_HEADERS), \
+          srcfname=`echo '$$(f)' | sed -e 's/^\(.*\)->.*$$$$/\1/'` ; destfname=`echo '$$(f)' | sed -e 's/^.*->\(.*\)$$$$/\1/'` ; \
+          cmp --quiet TODO_BUILD_DIR/$$$${srcfname} $(1)/$$$${destfname} \
+          || ( mkdir -p `dirname $(1)/$$$${destfname}` && $$(call cp_cmd,TODO_BUILD_DIR/$$$${srcfname},$(1)/$$$${destfname}) ) || exit 1 ; )
 endef
+
+# TODO: *_GEN_HEADERS should be copied by normal rules during build
+# phase because they are generated by another rule.
diff --git a/snippets/prepare.omk b/snippets/prepare.omk
new file mode 100644 (file)
index 0000000..c8285d6
--- /dev/null
@@ -0,0 +1,59 @@
+
+################
+# Prepare pass #
+################
+
+$(eval $(call omk_pass_template,prepare-pass))
+
+###
+# Name of the prepared rule.  This name is used as prefix of variable
+# names in .omk.inc and is based on the first target
+omk_inc_rule = $(firstword $(1:$(OUTPUT_DIR)/%=%))
+
+# The name of .omk.inc file is derived from $(omk_inc_rule) and
+# depends whether the target is under _build or elsewhere.
+omk_inc_file = $(if $(filter $(BUILD_DIR_NAME)%,$(omk_inc_rule)),\
+                   $(OMK_WORK_DIR)/$(notdir $(omk_inc_rule)).omk.inc,\
+                   $(OMK_WORK_DIR)/$(subst /,_,$(omk_inc_rule)).omk.inc)
+
+target_omk_file = $(OMK_WORK_DIR)/$(notdir $(1)).target.omk
+
+# >\< substitution to preserve \ in echo argument
+# >'< substitution is for echo to work,
+# >$< substitution to preserve $ when reloading .omk.inc file
+subst-cmd = $(subst $$,$$$$,$(call escsq,$(subst \,\\,$(1))))
+
+###
+# prepare_rule is used to generate .omk.inc files during prepare-pass.
+# All paths in this file should be relative to $(OUTPUT_DIR)
+# Usage: $(eval $(call prepare_rule,<targets>,<deps>,<msg>,<cmd>))
+define prepare_rule
+prepare-pass::
+#TODO remove echos from the next commands
+       @set -e;\
+           echo 'prepared_rules += $(omk_inc_rule)' > $(omk_inc_file).tmp; \
+           echo '$(omk_inc_rule)_targets = $$(call strip_out,$(1))' >> $(omk_inc_file).tmp; \
+           echo '$(omk_inc_rule)_deps += $$(call strip_out,$(2))' >> $(omk_inc_file).tmp; \
+           echo '$(omk_inc_rule)_msg = $(3)' >> $(omk_inc_file).tmp; \
+           echo '$(omk_inc_rule)_cmd = $(call subst-cmd,$(4))' >> $(omk_inc_file).tmp; \
+       if cmp -s $(omk_inc_file).tmp $(omk_inc_file); then rm $(omk_inc_file).tmp; echo "  CHK     "$$(call strip_out,$(omk_inc_file)); else mv $(omk_inc_file).tmp $(omk_inc_file); echo "  UPD     "$$(call strip_out,$(omk_inc_file)); fi
+endef
+
+###
+# prepare_rule_goal - same as prepare rules but the target is put
+# as dependency to the default goal, which causes it to be built
+# upon calling make
+define prepare_rule_goal
+$(call prepare_rule,$(1),$(2),$(3),$(4))
+prepared_goals += $(call strip_out,$(1))
+endef
+
+_goals := $(OMK_WORK_DIR)/__goals.omk.inc
+
+prepare-pass::
+       @echo 'omk_goals += $(prepared_goals)' > $(_goals).tmp; \
+           if cmp -s $(_goals).tmp $(_goals); \
+               then rm $(_goals).tmp; \
+               else mv $(_goals).tmp $(_goals); fi
+
+
index b9212970c86993534ac31adad74ead00c169f83c..101d10dcd89572c0689c70f11338fe32f5a4b5fa 100644 (file)
@@ -1,48 +1,49 @@
-# QT_PROJECTS     .. list of QT .pro file to use for compilation
-# QT_SUBDIRS       .. subdirectories where to build QT applications using qmake (depricated)
+# QT_SUBDIRS       .. subdirectories where to build QT applications using qmake
 # QTDIR                   .. where QT resides
 
-ifneq ($(QT_SUBDIRS)$(QT_PROJECTS),)
+ifneq ($(QT_SUBDIRS),)
 
-# Usage: $(call qt_project_template,<.pro_file relative to SOURCES_DIR>)
-define qt_project_template
+.PHONY: qt-subpass clean-qt distclean-qt
 
-.PHONY: qt-subpass-$(1) clean-qt-$(dir $(1))
-
-# FIXME: Handle multiple .pro files correctly
-$(LOCAL_BUILD_DIR)/$(dir $(1))Makefile: $(SOURCES_DIR)/$(1)
-       $(Q)mkdir -p $$(dir $$(@)) && cd $$(dir $$(@)) &&               \
-       $(QTDIR:%=%/bin/)qmake                                          \
-            TOP_DIR=$(OUTPUT_DIR)                                      \
-            RELATIVE_DIR=$(RELATIVE_PREFIX)$(dir $(1))                 \
-            $(QTDIR:%=QTDIR=%) CC=$(CC) CXX=$(CXX)                     \
-            LIBS+="-L$(USER_LIB_DIR)" DESTDIR=$(USER_BIN_DIR)          \
-            INCLUDEPATH+="$(USER_INCLUDE_DIR)"                         \
-            QMAKE_LFLAGS="-Wl,-rpath-link,$(USER_LIB_DIR) $$(QMAKE_LFLAGS)" \
-            $(SOURCES_DIR)/$(1)
+# Usage: $(call qt_makefile_template,<qt-subdir>)
+define qt_makefile_template
+$(SOURCES_DIR)/$(1)/Makefile: $(wildcard $(SOURCES_DIR)/$(1)/*.pro)
+       cd $(SOURCES_DIR)/$(1); $(QTDIR:%=%/bin/)qmake TOP_DIR=$(OUTPUT_DIR) \
+            RELATIVE_DIR=$(RELATIVE_PREFIX)$(1) $(QTDIR:%=QTDIR=%) CC=$(CC) \
+            CXX=$(CXX) LIBS+="-L$(USER_LIB_DIR)" INCLUDEPATH+="$(USER_INCLUDE_DIR)"
+endef
+$(foreach dir,$(QT_SUBDIRS), $(eval $(call qt_makefile_template,$(dir))))
 
-# This horrible substitution is here to properly escape
-# -Wl,-rpath,$ORIGIN flags. It includes escaping for make, shell,
-# qmake and again make and shell run on qmake generated makefile.
-QMAKE_LFLAGS = $$(subst $$$$,\\\\\\$$$$\$$$$,$$(LDFLAGS))
+qt-subpass: $(foreach dir,$(QT_SUBDIRS), $(SOURCES_DIR)/$(dir)/Makefile)
+       $(foreach dir,$(QT_SUBDIRS),\
+               $(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(dir) \
+               RELATIVE_DIR=$(RELATIVE_PREFIX)$(dir) -C $(SOURCES_DIR)/$(dir) \
+               -f $(SOURCES_DIR)/$(dir)/Makefile || exit 1 ;)
 
 # Hook to binary pass
-binary-pass-submakes: qt-subpass-$(1)
-qt-subpass-$(1): $(LOCAL_BUILD_DIR)/$(dir $(1))Makefile
-       $(Q)$(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(dir $(1)) \
-               RELATIVE_DIR=$(RELATIVE_PREFIX)$(dir $(1)) -C $(LOCAL_BUILD_DIR)/$(dir $(1)) || exit 1 ;
+binary-pass-submakes: qt-subpass
 
 # Hook to clean pass
-clean-local: clean-qt-$(dir $(1))
-clean-qt-$(dir $(1)): $(LOCAL_BUILD_DIR)/$(dir $(1))Makefile
-       @$(QUIET_CMD_ECHO) "  QT CLEAN $(dir $(1))"
-       $(Q)$(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(dir $(1)) \
-         RELATIVE_DIR=$(RELATIVE_PREFIX)$(dir $(1)) \
-         -C $(LOCAL_BUILD_DIR)/$(dir $(1)) clean
-       $(Q)rm $(LOCAL_BUILD_DIR)/$(dir $(1))Makefile
-endef
-
-$(foreach pro,$(QT_PROJECTS), $(eval $(call qt_project_template,$(pro))))
-$(foreach pro,$(foreach dir,$(QT_SUBDIRS), $(wildcard $(dir)/*.pro)), $(eval $(call qt_project_template,$(pro))))
-
+clean-local: clean-qt
+clean-qt:
+       +@$(foreach dir, $(QT_SUBDIRS), \
+               $(if $(wildcard $(SOURCES_DIR)/$(dir)/Makefile), \
+               @$(QUIET_CMD_ECHO) "  CLEAN   $(dir)"; \
+               $(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(dir) \
+               RELATIVE_DIR=$(RELATIVE_PREFIX)$(dir) -C $(SOURCES_DIR)/$(dir) \
+               -f $(SOURCES_DIR)/$(dir)/Makefile clean|| exit 1 ;))
+
+
+# Hook to distclean
+distclean: distclean-qt
+
+# TODO: Add distclean-qt-pass to handle QT_SUBDIRS in the whole
+# tree. This way we only distclean toplevel subdirs.
+distclean-qt:
+       +@$(foreach dir, $(QT_SUBDIRS), \
+               $(if $(wildcard $(SOURCES_DIR)/$(dir)/Makefile), \
+               @$(QUIET_CMD_ECHO) "  DISTCLEAN $(dir)"; \
+               $(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(dir) \
+               RELATIVE_DIR=$(RELATIVE_PREFIX)$(dir) -C $(SOURCES_DIR)/$(dir) \
+               -f $(SOURCES_DIR)/$(dir)/Makefile distclean|| exit 1 ;))
 endif