244 ifneq ($(TOOLCHAIN_TYPE), microsoft) 245 ifeq ($(TOOLCHAIN_TYPE)$$(filter %.s,$2), solstudio) 246 # The Solaris studio compiler doesn't output the full path to the object file in the 247 # generated deps files. Fixing it with sed. If compiling assembly, don't try this. 248 $(call LogFailures, $$($1_$2_OBJ).log, $$($1_SAFE_NAME)_$$(notdir $2), \ 249 $$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP).tmp $(CC_OUT_OPTION)$$($1_$2_OBJ) $2) 250 $(SED) 's|^$$(@F):|$$@:|' $$($1_$2_DEP).tmp > $$($1_$2_DEP) 251 else 252 $(call LogFailures, $$($1_$2_OBJ).log, $$($1_SAFE_NAME)_$$(notdir $2), \ 253 $$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP) $(CC_OUT_OPTION)$$($1_$2_OBJ) $2) 254 endif 255 # Create a dependency target file from the dependency file. 256 # Solution suggested by http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ 257 ifneq ($$($1_$2_DEP),) 258 $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_$2_DEP) > $$($1_$2_DEP_TARGETS) 259 endif 260 else 261 # The Visual Studio compiler lacks a feature for generating make dependencies, but by 262 # setting -showIncludes, all included files are printed. These are filtered out and 263 # parsed into make dependences. 264 # Keep as much as possible on one execution line for best performance on Windows 265 $(RM) $$($1_$2_DEP).exitvalue ; \ 266 ($(call LogFailures, $$($1_$2_OBJ).log, $$($1_SAFE_NAME)_$$(notdir $2), \ 267 $$($1_$2_COMP) $$($1_$2_FLAGS) -showIncludes $$($1_$2_DEBUG_OUT_FLAGS) \ 268 $(CC_OUT_OPTION)$$($1_$2_OBJ) $2) || echo $$$$? > $$($1_$2_DEP).exitvalue ) \ 269 | $(TEE) $$($1_$2_DEP).raw | $(GREP) -v -e "^Note: including file:" \ 270 -e "^$(notdir $2)$$$$" || test "$$$$?" = "1" ; \ 271 ( test -s $$($1_$2_DEP).exitvalue \ 272 && exit `$(CAT) $$($1_$2_DEP).exitvalue` || true ) ; \ 273 ($(ECHO) $$@: \\ ; \ 274 $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_$2_DEP).raw) \ 275 | $(SORT) -u > $$($1_$2_DEP) ; \ 276 $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_$2_DEP) > $$($1_$2_DEP_TARGETS) 277 endif 278 endif 279 endef 280 281 # Setup make rules for creating a native binary (a shared library or an 282 # executable). 283 # 284 # Parameter 1 is the name of the rule. This name is used as variable prefix, 285 # and the targets generated are listed in a variable by that name. 286 # 287 # Remaining parameters are named arguments. These include: 288 # TOOLCHAIN Name of toolchain setup to use. Defaults to TOOLCHAIN_DEFAULT. 289 # SRC one or more directory roots to scan for C/C++ files. 290 # CFLAGS the compiler flags to be used, used both for C and C++. 291 # CXXFLAGS the compiler flags to be used for c++, if set overrides CFLAGS. 292 # LDFLAGS the linker flags to be used, used both for C and C++. 293 # LIBS the libraries to link to 294 # ARFLAGS the archiver flags to be used 295 # OBJECT_DIR the directory where we store the object files 641 $$(if $$(filter-out %.vardeps, $$?), \ 642 'due to $$(words $$(filter-out %.vardeps, $$?)) file(s)', \ 643 $$(if $$(filter %.vardeps, $$?), 'due to makefile changes'))) 644 endif 645 $(TOUCH) $$@ 646 647 # On windows we need to create a resource file 648 ifeq ($(OPENJDK_TARGET_OS), windows) 649 ifneq (,$$($1_VERSIONINFO_RESOURCE)) 650 $1_RES:=$$($1_OBJECT_DIR)/$$($1_BASENAME).res 651 $1_RES_DEP:=$$($1_RES).d 652 $1_RES_DEP_TARGETS:=$$($1_RES).d.targets 653 -include $$($1_RES_DEP) 654 -include $$($1_RES_DEP_TARGETS) 655 656 $1_RES_VARDEPS := $$($1_RC) $$($1_RC_FLAGS) 657 $1_RES_VARDEPS_FILE := $$(call DependOnVariable, $1_RES_VARDEPS, \ 658 $$($1_RES).vardeps) 659 660 $$($1_RES): $$($1_VERSIONINFO_RESOURCE) $$($1_RES_VARDEPS_FILE) 661 $(ECHO) $(LOG_INFO) "Compiling resource $$(notdir $$($1_VERSIONINFO_RESOURCE)) (for $$(notdir $$($1_TARGET)))" 662 $$($1_RC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) $(CC_OUT_OPTION)$$@ \ 663 $$($1_VERSIONINFO_RESOURCE) 664 # Windows RC compiler does not support -showIncludes, so we mis-use CL for this. 665 $$($1_CC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \ 666 $(CC_OUT_OPTION)$$($1_RES_DEP).obj $$($1_VERSIONINFO_RESOURCE) > $$($1_RES_DEP).raw 2>&1 || exit 0 667 ($(ECHO) $$($1_RES): \\ \ 668 && $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_RES_DEP).raw) > $$($1_RES_DEP) 669 $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_RES_DEP) > $$($1_RES_DEP_TARGETS) 670 endif 671 endif 672 673 # mapfile doesnt seem to be implemented on macosx (yet??) 674 ifneq ($(OPENJDK_TARGET_OS),macosx) 675 ifneq ($(OPENJDK_TARGET_OS),windows) 676 $1_REAL_MAPFILE:=$$($1_MAPFILE) 677 ifneq (,$$($1_REORDER)) 678 $1_REAL_MAPFILE:=$$($1_OBJECT_DIR)/mapfile 679 680 $$($1_REAL_MAPFILE) : $$($1_MAPFILE) $$($1_REORDER) 681 $$(MKDIR) -p $$(@D) 682 $$(CP) $$($1_MAPFILE) $$@.tmp 683 $$(SED) -e 's=OUTPUTDIR=$$($1_OBJECT_DIR)=' $$($1_REORDER) >> $$@.tmp 684 $$(MV) $$@.tmp $$@ 685 endif 686 endif 687 endif 688 784 $1_LD_OBJ_ARG := $$($1_ALL_OBJS) 785 786 # If there are many object files, use an @-file... 787 ifneq ($$(word 17, $$($1_ALL_OBJS)), ) 788 $1_OBJ_FILE_LIST := $$($1_OBJECT_DIR)/_$1_objectfilenames.txt 789 ifneq ($(COMPILER_COMMAND_FILE_FLAG),) 790 $1_LD_OBJ_ARG := $(COMPILER_COMMAND_FILE_FLAG)$$($1_OBJ_FILE_LIST) 791 else 792 # ...except for toolchains which don't support them. 793 $1_LD_OBJ_ARG := `cat $$($1_OBJ_FILE_LIST)` 794 endif 795 endif 796 797 $$($1_TARGET): $$($1_ALL_OBJS) $$($1_RES) $$($1_REAL_MAPFILE) \ 798 $$($1_VARDEPS_FILE) 799 ifneq ($$($1_OBJ_FILE_LIST), ) 800 $$(eval $$(call ListPathsSafely, $1_ALL_OBJS, $$($1_OBJ_FILE_LIST))) 801 endif 802 # Keep as much as possible on one execution line for best performance 803 # on Windows 804 $(ECHO) $(LOG_INFO) "Linking $$($1_BASENAME)" ; \ 805 $(call LogFailures, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link.log, $$($1_SAFE_NAME)_link, \ 806 $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \ 807 $(LD_OUT_OPTION)$$@ \ 808 $$($1_LD_OBJ_ARG) $$($1_RES) \ 809 $$($1_LIBS) $$($1_EXTRA_LIBS)) ; \ 810 $$($1_CREATE_DEBUGINFO_CMDS) 811 $$($1_STRIP_CMD) 812 813 endif 814 815 ifneq (,$$($1_STATIC_LIBRARY)) 816 $1_VARDEPS := $$($1_AR) $$($1_ARFLAGS) $$($1_LIBS) \ 817 $$($1_EXTRA_LIBS) 818 $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \ 819 $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps) 820 821 # Generating a static library, ie object file archive. 822 $$($1_TARGET): $$($1_ALL_OBJS) $$($1_RES) $$($1_VARDEPS_FILE) 823 $(ECHO) $(LOG_INFO) "Archiving $$($1_STATIC_LIBRARY)" 824 $(call LogFailures, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link.log, $$($1_SAFE_NAME)_link, \ 825 $$($1_AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_ALL_OBJS) \ 826 $$($1_RES)) 827 ifeq ($(STATIC_BUILD), true) 828 $(GetSymbols) 829 endif 830 endif 831 832 ifneq (,$$($1_PROGRAM)) 833 # A executable binary has been specified, setup the target for it. 834 $1_EXTRA_LIBS += $(GLOBAL_LIBS) 835 836 $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \ 837 $$($1_LIBS) $$($1_EXTRA_LIBS) $$($1_MT) \ 838 $$($1_CODESIGN) $$($1_CREATE_DEBUGINFO_CMDS) $$($1_MANIFEST_VERSION) \ 839 $$($1_STRIP_CMD) 840 $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \ 841 $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps) 842 843 $$($1_TARGET): $$($1_ALL_OBJS) $$($1_RES) $$($1_MANIFEST) \ 844 $$($1_VARDEPS_FILE) 845 $(ECHO) $(LOG_INFO) "Linking executable $$($1_BASENAME)" ; \ 846 $(call LogFailures, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link.log, $$($1_SAFE_NAME)_link, \ 847 $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \ 848 $(EXE_OUT_OPTION)$$($1_TARGET) \ 849 $$($1_ALL_OBJS) $$($1_RES) \ 850 $$($1_LIBS) $$($1_EXTRA_LIBS)) 851 ifeq ($(OPENJDK_TARGET_OS), windows) 852 ifneq ($$($1_MANIFEST), ) 853 $$($1_MT) -nologo -manifest $$($1_MANIFEST) -identity:"$$($1_PROGRAM).exe, version=$$($1_MANIFEST_VERSION)" -outputresource:$$@;#1 854 endif 855 endif 856 # This only works if the openjdk_codesign identity is present on the system. Let 857 # silently fail otherwise. 858 ifneq (,$(CODESIGN)) 859 ifneq (,$$($1_CODESIGN)) 860 $(CODESIGN) -s openjdk_codesign $$@ 861 endif 862 endif 863 $$($1_CREATE_DEBUGINFO_CMDS) 864 $$($1_STRIP_CMD) 865 | 244 ifneq ($(TOOLCHAIN_TYPE), microsoft) 245 ifeq ($(TOOLCHAIN_TYPE)$$(filter %.s,$2), solstudio) 246 # The Solaris studio compiler doesn't output the full path to the object file in the 247 # generated deps files. Fixing it with sed. If compiling assembly, don't try this. 248 $(call LogFailures, $$($1_$2_OBJ).log, $$($1_SAFE_NAME)_$$(notdir $2), \ 249 $$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP).tmp $(CC_OUT_OPTION)$$($1_$2_OBJ) $2) 250 $(SED) 's|^$$(@F):|$$@:|' $$($1_$2_DEP).tmp > $$($1_$2_DEP) 251 else 252 $(call LogFailures, $$($1_$2_OBJ).log, $$($1_SAFE_NAME)_$$(notdir $2), \ 253 $$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP) $(CC_OUT_OPTION)$$($1_$2_OBJ) $2) 254 endif 255 # Create a dependency target file from the dependency file. 256 # Solution suggested by http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ 257 ifneq ($$($1_$2_DEP),) 258 $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_$2_DEP) > $$($1_$2_DEP_TARGETS) 259 endif 260 else 261 # The Visual Studio compiler lacks a feature for generating make dependencies, but by 262 # setting -showIncludes, all included files are printed. These are filtered out and 263 # parsed into make dependences. 264 # Keep as much as possible on one execution line for best performance on Windows. 265 # No need to save exit code from compilation since pipefail is always active on 266 # Windows. 267 $(call LogFailures, $$($1_$2_OBJ).log, $$($1_SAFE_NAME)_$$(notdir $2), \ 268 $$($1_$2_COMP) $$($1_$2_FLAGS) -showIncludes $$($1_$2_DEBUG_OUT_FLAGS) \ 269 $(CC_OUT_OPTION)$$($1_$2_OBJ) $2) \ 270 | $(GREP) -v -e "^Note: including file:" \ 271 -e "^$(notdir $2)$$$$" || test "$$$$?" = "1" ; \ 272 $(ECHO) $$@: \\ > $$($1_$2_DEP) ; \ 273 $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_$2_OBJ).log \ 274 | $(SORT) -u >> $$($1_$2_DEP) ; \ 275 $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_$2_DEP) > $$($1_$2_DEP_TARGETS) 276 endif 277 endif 278 endef 279 280 # Setup make rules for creating a native binary (a shared library or an 281 # executable). 282 # 283 # Parameter 1 is the name of the rule. This name is used as variable prefix, 284 # and the targets generated are listed in a variable by that name. 285 # 286 # Remaining parameters are named arguments. These include: 287 # TOOLCHAIN Name of toolchain setup to use. Defaults to TOOLCHAIN_DEFAULT. 288 # SRC one or more directory roots to scan for C/C++ files. 289 # CFLAGS the compiler flags to be used, used both for C and C++. 290 # CXXFLAGS the compiler flags to be used for c++, if set overrides CFLAGS. 291 # LDFLAGS the linker flags to be used, used both for C and C++. 292 # LIBS the libraries to link to 293 # ARFLAGS the archiver flags to be used 294 # OBJECT_DIR the directory where we store the object files 640 $$(if $$(filter-out %.vardeps, $$?), \ 641 'due to $$(words $$(filter-out %.vardeps, $$?)) file(s)', \ 642 $$(if $$(filter %.vardeps, $$?), 'due to makefile changes'))) 643 endif 644 $(TOUCH) $$@ 645 646 # On windows we need to create a resource file 647 ifeq ($(OPENJDK_TARGET_OS), windows) 648 ifneq (,$$($1_VERSIONINFO_RESOURCE)) 649 $1_RES:=$$($1_OBJECT_DIR)/$$($1_BASENAME).res 650 $1_RES_DEP:=$$($1_RES).d 651 $1_RES_DEP_TARGETS:=$$($1_RES).d.targets 652 -include $$($1_RES_DEP) 653 -include $$($1_RES_DEP_TARGETS) 654 655 $1_RES_VARDEPS := $$($1_RC) $$($1_RC_FLAGS) 656 $1_RES_VARDEPS_FILE := $$(call DependOnVariable, $1_RES_VARDEPS, \ 657 $$($1_RES).vardeps) 658 659 $$($1_RES): $$($1_VERSIONINFO_RESOURCE) $$($1_RES_VARDEPS_FILE) 660 $$(call LogInfo, Compiling resource $$(notdir $$($1_VERSIONINFO_RESOURCE)) (for $$(notdir $$($1_TARGET)))) 661 $$($1_RC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) $(CC_OUT_OPTION)$$@ \ 662 $$($1_VERSIONINFO_RESOURCE) 663 # Windows RC compiler does not support -showIncludes, so we mis-use CL for this. 664 $$($1_CC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \ 665 $(CC_OUT_OPTION)$$($1_RES_DEP).obj $$($1_VERSIONINFO_RESOURCE) > $$($1_RES_DEP).raw 2>&1 || true ; \ 666 $(ECHO) $$($1_RES): \\ > $$($1_RES_DEP) ; \ 667 $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_RES_DEP).raw >> $$($1_RES_DEP) ; \ 668 $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_RES_DEP) > $$($1_RES_DEP_TARGETS) 669 endif 670 endif 671 672 # mapfile doesnt seem to be implemented on macosx (yet??) 673 ifneq ($(OPENJDK_TARGET_OS),macosx) 674 ifneq ($(OPENJDK_TARGET_OS),windows) 675 $1_REAL_MAPFILE:=$$($1_MAPFILE) 676 ifneq (,$$($1_REORDER)) 677 $1_REAL_MAPFILE:=$$($1_OBJECT_DIR)/mapfile 678 679 $$($1_REAL_MAPFILE) : $$($1_MAPFILE) $$($1_REORDER) 680 $$(MKDIR) -p $$(@D) 681 $$(CP) $$($1_MAPFILE) $$@.tmp 682 $$(SED) -e 's=OUTPUTDIR=$$($1_OBJECT_DIR)=' $$($1_REORDER) >> $$@.tmp 683 $$(MV) $$@.tmp $$@ 684 endif 685 endif 686 endif 687 783 $1_LD_OBJ_ARG := $$($1_ALL_OBJS) 784 785 # If there are many object files, use an @-file... 786 ifneq ($$(word 17, $$($1_ALL_OBJS)), ) 787 $1_OBJ_FILE_LIST := $$($1_OBJECT_DIR)/_$1_objectfilenames.txt 788 ifneq ($(COMPILER_COMMAND_FILE_FLAG),) 789 $1_LD_OBJ_ARG := $(COMPILER_COMMAND_FILE_FLAG)$$($1_OBJ_FILE_LIST) 790 else 791 # ...except for toolchains which don't support them. 792 $1_LD_OBJ_ARG := `cat $$($1_OBJ_FILE_LIST)` 793 endif 794 endif 795 796 $$($1_TARGET): $$($1_ALL_OBJS) $$($1_RES) $$($1_REAL_MAPFILE) \ 797 $$($1_VARDEPS_FILE) 798 ifneq ($$($1_OBJ_FILE_LIST), ) 799 $$(eval $$(call ListPathsSafely, $1_ALL_OBJS, $$($1_OBJ_FILE_LIST))) 800 endif 801 # Keep as much as possible on one execution line for best performance 802 # on Windows 803 $$(call LogInfo, Linking $$($1_BASENAME)) 804 $(call LogFailures, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link.log, $$($1_SAFE_NAME)_link, \ 805 $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \ 806 $(LD_OUT_OPTION)$$@ \ 807 $$($1_LD_OBJ_ARG) $$($1_RES) \ 808 $$($1_LIBS) $$($1_EXTRA_LIBS)) ; \ 809 $$($1_CREATE_DEBUGINFO_CMDS) 810 $$($1_STRIP_CMD) 811 812 endif 813 814 ifneq (,$$($1_STATIC_LIBRARY)) 815 $1_VARDEPS := $$($1_AR) $$($1_ARFLAGS) $$($1_LIBS) \ 816 $$($1_EXTRA_LIBS) 817 $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \ 818 $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps) 819 820 # Generating a static library, ie object file archive. 821 $$($1_TARGET): $$($1_ALL_OBJS) $$($1_RES) $$($1_VARDEPS_FILE) 822 $$(call LogInfo, Archiving $$($1_STATIC_LIBRARY)) 823 $(call LogFailures, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link.log, $$($1_SAFE_NAME)_link, \ 824 $$($1_AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_ALL_OBJS) \ 825 $$($1_RES)) 826 ifeq ($(STATIC_BUILD), true) 827 $(GetSymbols) 828 endif 829 endif 830 831 ifneq (,$$($1_PROGRAM)) 832 # A executable binary has been specified, setup the target for it. 833 $1_EXTRA_LIBS += $(GLOBAL_LIBS) 834 835 $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \ 836 $$($1_LIBS) $$($1_EXTRA_LIBS) $$($1_MT) \ 837 $$($1_CODESIGN) $$($1_CREATE_DEBUGINFO_CMDS) $$($1_MANIFEST_VERSION) \ 838 $$($1_STRIP_CMD) 839 $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \ 840 $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps) 841 842 $$($1_TARGET): $$($1_ALL_OBJS) $$($1_RES) $$($1_MANIFEST) \ 843 $$($1_VARDEPS_FILE) 844 $$(call LogInfo, Linking executable $$($1_BASENAME)) 845 $(call LogFailures, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link.log, $$($1_SAFE_NAME)_link, \ 846 $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \ 847 $(EXE_OUT_OPTION)$$($1_TARGET) \ 848 $$($1_ALL_OBJS) $$($1_RES) \ 849 $$($1_LIBS) $$($1_EXTRA_LIBS)) 850 ifeq ($(OPENJDK_TARGET_OS), windows) 851 ifneq ($$($1_MANIFEST), ) 852 $$($1_MT) -nologo -manifest $$($1_MANIFEST) -identity:"$$($1_PROGRAM).exe, version=$$($1_MANIFEST_VERSION)" -outputresource:$$@;#1 853 endif 854 endif 855 # This only works if the openjdk_codesign identity is present on the system. Let 856 # silently fail otherwise. 857 ifneq (,$(CODESIGN)) 858 ifneq (,$$($1_CODESIGN)) 859 $(CODESIGN) -s openjdk_codesign $$@ 860 endif 861 endif 862 $$($1_CREATE_DEBUGINFO_CMDS) 863 $$($1_STRIP_CMD) 864 |