1 #
   2 # Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
   3 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4 #
   5 # This code is free software; you can redistribute it and/or modify it
   6 # under the terms of the GNU General Public License version 2 only, as
   7 # published by the Free Software Foundation.  Oracle designates this
   8 # particular file as subject to the "Classpath" exception as provided
   9 # by Oracle in the LICENSE file that accompanied this code.
  10 #
  11 # This code is distributed in the hope that it will be useful, but WITHOUT
  12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14 # version 2 for more details (a copy is included in the LICENSE file that
  15 # accompanied this code).
  16 #
  17 # You should have received a copy of the GNU General Public License version
  18 # 2 along with this work; if not, write to the Free Software Foundation,
  19 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20 #
  21 # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22 # or visit www.oracle.com if you need additional information or have any
  23 # questions.
  24 #
  25 
  26 ifeq (,$(_MAKEBASE_GMK))
  27   $(error You must include MakeBase.gmk prior to including Execute.gmk)
  28 endif
  29 
  30 ################################################################################
  31 #
  32 # Code for handling the SetupExecute macro.
  33 #
  34 ################################################################################
  35 
  36 
  37 ################################################################################
  38 # Setup make rules for executing an arbitrary command.
  39 #
  40 # Parameter 1 is the name of the rule. This name is used as variable prefix,
  41 # and the targets generated are listed in a variable by that name.
  42 #
  43 # You need to specify a COMMAND, the actual command line to execute. You are
  44 # strongly recommended to provide a INFO with the text to display for LOG=info
  45 # on what operation is performed. You can use DEPS to provide additional
  46 # dependencies for your command to run. You can optionally include a PRE_COMMAND
  47 # and a POST_COMMAND, intended for simple pre- and post-processing. The latter
  48 # might be e.g. a mv from a temporary file to the final destination, the former
  49 # e.g. a simple sed replacement on the input file. If the operations are
  50 # unrelated to the main COMMAND, this is not a suitable solution.
  51 #
  52 # If your command outputs a variety of files, or if it's really a single file
  53 # but you don't really care about the output from the perspective, you can just
  54 # supply an OUTPUT_DIR. You are supposed to make sure the command creates files
  55 # in this directory (which will be created for you if it does not exist), but
  56 # this can't be enforced by SetupExecute. Additional support files (like logs
  57 # and markers) are created in this directory. If you want support files in a
  58 # separate directory (e.g. if you're targeting an OUTPUT_DIR in the image
  59 # directly), you can specify a SUPPORT_DIR. If your command outputs only a
  60 # single file, you can get rid of the marker files (but not the log files) by
  61 # specifying OUTPUT_FILE. Note that if you specify an OUTPUT_FILE, support log
  62 # files will be placed in the same directory as the OUTPUT_FILE. If you do not
  63 # want that, use SUPPORT_DIR as well.
  64 #
  65 # After the call to SetupExecute, $1 will contain references to all generated
  66 # files (that make knows about), and $1_TARGET will contain a reference to the
  67 # final target (that is OUTPUT_FILE if it exists, or the $1_exec.marker file
  68 # otherwise).
  69 #
  70 # All the above keep functioning as expected even if PRE_COMMAND and
  71 # POST_COMMAND are given. One special case worth noting is that if OUTPUT_FILE
  72 # and POST_COMMAND is both given, the actual OUTPUT_FILE is considered to be a
  73 # result of running the POST_COMMAND.
  74 #
  75 # Remaining parameters are named arguments. These include:
  76 #   COMMAND     : The command to execute
  77 #   PRE_COMMAND : A helper command to execute before COMMAND
  78 #   POST_COMMAND: A helper command to execute after COMMAND
  79 #   OUTPUT_DIR  : The directory that will contain the result from the command
  80 #   OUTPUT_FILE : Use this if the command results in a single output file
  81 #   SUPPORT_DIR : Where to store generated support files
  82 #   INFO        : Message to display at LOG=info level when running command (optional)
  83 #   WARN        : Message to display at LOG=warn level when running command (optional)
  84 #   DEPS        : Dependencies for the execution to take place
  85 #
  86 
  87 # Setup make rules for copying files, with an option to do more complex
  88 SetupExecute = $(NamedParamsMacroTemplate)
  89 define SetupExecuteBody
  90   ifeq ($$($1_COMMAND), )
  91     $$(error COMMAND is missing in SetupExecute $1)
  92   endif
  93 
  94   ifneq ($$($1_OUTPUT_FILE), )
  95     ifneq ($$($1_OUTPUT_DIR), )
  96       $$(error Cannot specify both OUTPUT_DIR and OUTPUT_FILE in SetupExecute $1)
  97     endif
  98     # We need to know output dir since we will make sure it is created.
  99     $1_OUTPUT_DIR := $$(patsubst %/,%, $$(dir $$($1_OUTPUT_FILE)))
 100     ifeq ($$($1_SUPPORT_DIR), )
 101       # If support dir is not given, use base dir of output file.
 102       $1_SUPPORT_DIR := $$($1_OUTPUT_DIR)
 103     endif
 104   else ifneq ($$($1_OUTPUT_DIR), )
 105     ifeq ($$($1_SUPPORT_DIR), )
 106       # If support dir is not given, use output dir.
 107       $1_SUPPORT_DIR := $$($1_OUTPUT_DIR)
 108     endif
 109   else
 110     $$(error OUTPUT_DIR or OUTPUT_FILE is required in SetupExecute $1)
 111   endif
 112 
 113   $1_BASE := $$($1_SUPPORT_DIR)/_$1
 114   $1_PRE_MARKER := $$($1_BASE)_pre.marker
 115   $1_EXEC_MARKER := $$($1_BASE)_exec.marker
 116   $1_POST_MARKER := $$($1_BASE)_post.marker
 117 
 118   ifeq ($$($1_OUTPUT_FILE), )
 119     # No specified output file, use markers everywhere
 120     $1_EXEC_RESULT := $$($1_EXEC_MARKER)
 121     ifeq ($$($1_POST_COMMAND), )
 122       $1_FINAL_RESULT := $$($1_EXEC_MARKER)
 123     else
 124       $1_FINAL_RESULT := $$($1_POST_MARKER)
 125     endif
 126 
 127   else
 128     # If we have a single output file, we don't need a separate marker
 129 
 130     ifeq ($$($1_POST_COMMAND), )
 131       $1_EXEC_RESULT := $$($1_OUTPUT_FILE)
 132       $1_FINAL_RESULT := $$($1_EXEC_RESULT)
 133     else
 134       $1_EXEC_RESULT := $$($1_EXEC_MARKER)
 135       $1_FINAL_RESULT := $$($1_OUTPUT_FILE)
 136     endif
 137 
 138   endif
 139 
 140   ifeq ($$($1_INFO)$$($1_WARN), )
 141     # If neither info nor warn is provided, add basic info text.
 142     $1_INFO := Running commands for $1
 143   endif
 144 
 145   ifneq ($$($1_PRE_COMMAND), )
 146 
 147     $$($1_PRE_MARKER): $$($1_DEPS)
 148         ifneq ($$($1_WARN), )
 149           $$(call LogWarn, $$($1_WARN))
 150         endif
 151         ifneq ($$($1_INFO), )
 152           $$(call LogInfo, $$($1_INFO))
 153         endif
 154         $$(call MakeDir, $$($1_SUPPORT_DIR) $$($1_OUTPUT_DIR))
 155         $$(call ExecuteWithLog, $$($1_BASE)_pre, \
 156             $$($1_PRE_COMMAND))
 157         $$(TOUCH) $$@
 158 
 159     $$($1_EXEC_RESULT): $$($1_PRE_MARKER)
 160         $$(call ExecuteWithLog, $$($1_BASE)_exec, \
 161             $$($1_COMMAND))
 162         ifeq ($$($1_EXEC_RESULT), $$($1_EXEC_MARKER))
 163           $$(TOUCH) $$@
 164         endif
 165 
 166     $1 := $$($1_PRE_MARKER) $$($1_EXEC_RESULT)
 167   else
 168     $$($1_EXEC_RESULT): $$($1_DEPS)
 169         ifneq ($$($1_WARN), )
 170           $$(call LogWarn, $$($1_WARN))
 171         endif
 172         ifneq ($$($1_INFO), )
 173           $$(call LogInfo, $$($1_INFO))
 174         endif
 175         $$(call MakeDir, $$(call EncodeSpace, $$($1_SUPPORT_DIR)) $$(call EncodeSpace, $$($1_OUTPUT_DIR)))
 176         $$(call ExecuteWithLog, $$($1_BASE)_exec, \
 177             $$($1_COMMAND))
 178         ifeq ($$($1_EXEC_RESULT), $$($1_EXEC_MARKER))
 179           $$(TOUCH) $$@
 180         endif
 181 
 182     $1 := $$($1_EXEC_RESULT)
 183   endif
 184 
 185   ifneq ($$($1_POST_COMMAND), )
 186 
 187     $$($1_FINAL_RESULT): $$($1_EXEC_RESULT)
 188         $$(call ExecuteWithLog, $$($1_BASE)_post, \
 189             $$($1_POST_COMMAND))
 190         $$(TOUCH) $$@
 191 
 192     $1 += $$($1_FINAL_RESULT)
 193   endif
 194 
 195   # Export all our generated targets in $1, and the final target in $1_TARGET.
 196   $1_TARGET := $$($1_FINAL_RESULT)
 197 
 198 endef