#-----------------------------------------------------------------------------# # vim: ts=8 sw=8 noexpandtab ft=make #-----------------------------------------------------------------------------# # Copyright (C) 1995-2010 The University of Melbourne. # Copyright (C) 2013, 2015-2016, 2022-2024 The Mercury team. # This file may only be copied under the terms of the GNU General # Public License - see the file COPYING in the Mercury distribution. #-----------------------------------------------------------------------------# # # Mmake.rules - rules for building Mercury programs # # N.B. All the builtin rules must use $@ as the target, so that they work # when $(VPATH) is set. # # When passing a module to mmc, strip off the directory part of the name. # This way the compiler will report an error if the source file is in another # directory, rather than generating interface files in the wrong directory. main_target: $(MAIN_TARGET) #-----------------------------------------------------------------------------# # Note that the order of suffixes is significant. .SUFFIXES: .m .err \ .int0 .int .int2 .int3 .opt .trans_opt \ .dep .depend .depend_ints .dv .doit .ugly \ .date0 .date .date3 .optdate .trans_opt_date \ .c .$O .pic_o \ .i .s .pic_s \ .java .class \ .dll .exe .cpp .cs \ .c_date .java_date .s_date .pic_s_date #-----------------------------------------------------------------------------# # # Code to set variables based on the setting of MMAKE_USE_SUBDIRS # (i.e. --use-subdirs). # ifeq ($(MMAKE_USE_SUBDIRS),yes) MCFLAGS += --use-subdirs ALL_MGNUCFLAGS += -I. -I$(mhs_subdir). -I$(mihs_subdir). endif #-----------------------------------------------------------------------------# .PRECIOUS: $(date0s_subdir)%.date0 .PRECIOUS: $(dates_subdir)%.date .PRECIOUS: $(date3s_subdir)%.date3 .PRECIOUS: $(optdates_subdir)%.optdate .PRECIOUS: $(trans_opt_dates_subdir)%.trans_opt_date .PRECIOUS: $(c_dates_subdir)%.c_date .PRECIOUS: $(java_dates_subdir)%.java_date .PRECIOUS: $(s_dates_subdir)%.s_date .PRECIOUS: $(pic_s_dates_subdir)%.pic_s_date #-----------------------------------------------------------------------------# # # Rules for building dependency files. # # When creating the dependencies with `--use-subdirs' enabled, we need # to create the `Mercury/dates' directories manually in order to # get things started. This should not be necessary, but there is a bug # in GNU Make with regard to directory caching. I have sent off a bug report # to the GNU Make maintainers (19 March 1998). -fjh. ifneq ($(MMAKE_USE_MMC_MAKE),yes) # NOTE The next three blocks specify the rules for the targets # # %.dep and %.dv # %.depend # %.depend_ints # # respectively. # # The reason why the first two blocks were initially duplicated was that # making %.dep (which is a real file) the source for the phony target %.depend, # which would have avoided the duplication, does not work, for two separate # reasons. The first reason is that with this setup, invoking mmake with # the .depend target would result in mmake *deleting* the .dep file after # making it, considering it to be an "intermediate" file. The second reason # is that "mmake depend" won't rebuild the .dep file if it already exists. # # The reason why the third block is separate from the first is the same as # the reason above. The third block is separate from the second because # it wants to invoke the Mercury compiler with different arguments. # # The bulk of each block is actually code for creating directories. # The comments on the original versions of these rules say that # # - the code for creating the classes_subdir is there because javac # does not create the destination directory for .class files, while # # - the code for creating the *other* directories is there to work around # a bug in GNU make. # # The *last* of these comments is from 2005; others are from earlier. # I (zs) don't know to what extent, if any, the issues they complain about # still exist. # # This code for creating directories is duplicated *within* each block # as well as *across* the blocks. The two copies within each block # differ only by a @. I (zs) don't why that is, but it was done intentionally. MMAKE_USE_SUBDIRS_EXPLICIT ?= no # NEARLY-IDENTICAL BLOCK 1 $(deps_subdir)%.dep $(deps_subdir)%.dv: $(MCD) $(ALL_GRADEFLAGS) $(ALL_MCDFLAGS) $* > $(*F).dep_err 2>&1 ifeq ($(MMAKE_USE_SUBDIRS),yes) ifeq ($(MMAKE_USE_SUBDIRS_EXPLICIT),yes) -mkdir -p $(classes_subdir) \ Mercury/dates Mercury/date0s Mercury/date3s \ Mercury/optdates Mercury/trans_opt_dates \ Mercury/c_dates else @-mkdir -p $(classes_subdir) \ Mercury/dates Mercury/date0s Mercury/date3s \ Mercury/optdates Mercury/trans_opt_dates \ Mercury/c_dates endif endif # NEARLY-IDENTICAL BLOCK 2 .PHONY: %.depend %.depend: $(MCD) $(ALL_GRADEFLAGS) $(ALL_MCDFLAGS) $* > $(*F).dep_err 2>&1 ifeq ($(MMAKE_USE_SUBDIRS),yes) ifeq ($(MMAKE_USE_SUBDIRS_EXPLICIT),yes) -mkdir -p $(classes_subdir) \ Mercury/dates Mercury/date0s Mercury/date3s \ Mercury/optdates Mercury/trans_opt_dates \ Mercury/c_dates else @-mkdir -p $(classes_subdir) \ Mercury/dates Mercury/date0s Mercury/date3s \ Mercury/optdates Mercury/trans_opt_dates \ Mercury/c_dates endif endif # NEARLY-IDENTICAL BLOCK 3 .PHONY: %.depend_ints %.depend_ints: $(MCDI) $(ALL_GRADEFLAGS) $(ALL_MCDIFLAGS) $* > $(*F).dep_err 2>&1 ifeq ($(MMAKE_USE_SUBDIRS),yes) ifeq ($(MMAKE_USE_SUBDIRS_EXPLICIT),yes) -mkdir -p $(classes_subdir) \ Mercury/dates Mercury/date0s Mercury/date3s \ Mercury/optdates Mercury/trans_opt_dates \ Mercury/c_dates else @-mkdir -p $(classes_subdir) \ Mercury/dates Mercury/date0s Mercury/date3s \ Mercury/optdates Mercury/trans_opt_dates \ Mercury/c_dates endif endif endif # MMAKE_USE_MMC_MAKE != yes #-----------------------------------------------------------------------------# # # Rules for building interface files. # WARNING: any changes here will probably need to be duplicated # in compiler/write_deps_file.m. # ifneq ($(MMAKE_USE_MMC_MAKE),yes) $(date0s_subdir)%.date0: %.m $(MCPI) $(ALL_GRADEFLAGS) $(ALL_MCPIFLAGS) $(*F) $(dates_subdir)%.date: %.m $(MCI) $(ALL_GRADEFLAGS) $(ALL_MCIFLAGS) $(*F) $(date3s_subdir)%.date3: %.m $(MCSI) $(ALL_GRADEFLAGS) $(ALL_MCSIFLAGS) $(*F) $(optdates_subdir)%.optdate: %.m $(MCOI) $(ALL_GRADEFLAGS) $(ALL_MCOIFLAGS) $(*F) $(trans_opt_dates_subdir)%.trans_opt_date: %.m $(MCTOI) $(ALL_GRADEFLAGS) $(ALL_MCTOIFLAGS) $(*F) # Be very careful about changing the following rules. # The `@:' is a silent do-nothing command. # It is used to force GNU Make to recheck the timestamp on the target file. # (It is a pity that GNU Make doesn't have a way of handling these sorts # of rules in a nicer manner.) $(int0s_subdir)%.int0: $(date0s_subdir)%.date0 @: $(ints_subdir)%.int: $(dates_subdir)%.date @: $(int2s_subdir)%.int2: $(dates_subdir)%.date @: $(int3s_subdir)%.int3: $(date3s_subdir)%.date3 @: $(opts_subdir)%.opt: $(optdates_subdir)%.optdate @: $(trans_opts_subdir)%.trans_opt: $(trans_opt_dates_subdir)%.trans_opt_date @: endif # MMAKE_USE_MMC_MAKE != yes #-----------------------------------------------------------------------------# # # Rules for compiling Mercury source files. # WARNING: any changes here will probably need to be duplicated # in compiler/write_deps_file.m. # ifneq ($(MMAKE_USE_MMC_MAKE),yes) # C back-end. # When smart recompilation finds that a module does not need to be recompiled, # it only touches the `.c_date' file. $(cs_subdir)%.c: $(c_dates_subdir)%.c_date @: $(c_dates_subdir)%.c_date: %.m $(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) $(*F) $(ERR_REDIRECT) # Java back-end. ifeq ($(MMAKE_USE_SUBDIRS),yes) $(classes_subdir)%.class: $(javas_subdir)%.java $(JAVAC) $(ALL_JAVACFLAGS) -d $(classes_subdir) $< else $(classes_subdir)%.class: $(javas_subdir)%.java $(JAVAC) $(ALL_JAVACFLAGS) $< endif # When smart recompilation finds that a module does not need to be recompiled, # it only touches the `.java_date' file. $(javas_subdir)%.java: $(java_dates_subdir)%.java_date @: $(java_dates_subdir)%.java_date: %.m $(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) \ --java-only $(*F) $(ERR_REDIRECT) # The `touch' is necessary. If it weren't there, and both the old and the # new .err files are zero size, the timestamp would not get updated. # The timestamp is updated by the write system call: if the new file # is zero size, write is never called. `touch' has code to test specifically # for this situation, and adds a byte to the file and then removes it. %.err: %.m $(MCE) $(ALL_GRADEFLAGS) $(ALL_MCFLAGS) $(*F) $(ERR_REDIRECT) @touch $@ endif # MMAKE_USE_MMC_MAKE != yes %.ugly: %.m $(MC) --convert-to-mercury $(ALL_GRADEFLAGS) $(ALL_MCFLAGS) $(*F) #-----------------------------------------------------------------------------# # # Rules for compiling C files in the user's source directory. # # There is a near-identical of the rule for %.$O in ../Mmake.common.in # (search for %.pseudo_o). Any changes to the rule here should be made # there as well. # %.$O: %.c $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) -c $< $(OBJFILE_OPT)$@ %.pic_o: %.c $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) $(CFLAGS_FOR_PIC) \ -c $< $(OBJFILE_OPT)$@ %.s: %.c $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) -S $< -o $@ %.pic_s: %.c $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) $(CFLAGS_FOR_PIC) \ -S $< -o $@ %.i: %.c $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) -E $< > $@ #-----------------------------------------------------------------------------# # # Rules for compiling C files in a subdirectory. # Note that we need both these rules and the ones above, # since even if the compiler generates all of its files in subdirectories, # the user may have some C files of their own which need to be compiled. # ifneq ($(MMAKE_USE_MMC_MAKE),yes) ifneq ("$(cs_subdir)","") $(os_subdir)%.$O: $(cs_subdir)%.c $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) -c $< $(OBJFILE_OPT)$@ $(os_subdir)%.pic_o: $(cs_subdir)%.c $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) $(CFLAGS_FOR_PIC) \ -c $< -o $@ %.s: $(cs_subdir)%.c $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) -S $< -o $@ %.pic_s: $(cs_subdir)%.c $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) $(CFLAGS_FOR_PIC) \ -S $< -o $@ %.i: $(cs_subdir)%.c $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) -E $< > $@ endif # $(cs_subdir) != "" endif # $(MMAKE_USE_MMC_MAKE) != yes #-----------------------------------------------------------------------------# ifeq ($(MMAKE_USE_MMC_MAKE),yes) # Always attempt to rebuild these files, even if they exist. .PHONY: $(ALL_MC_BUILD_FILES) *.err $(ALL_MC_BUILD_FILES): $(MCM) $@ %.err: $(MCM) $@ # If we don't know how to make the file, try using `mmc --make'. .DEFAULT: $(MCM) $@ clean_local: $(MCM) $(MERCURY_MAIN_MODULES:%=%.clean) realclean_local: $(MCM) $(MERCURY_MAIN_MODULES:%=%.realclean) endif # $(MMAKE_USE_MMC_MAKE) == yes #-----------------------------------------------------------------------------# # # Targets for cleaning up. # # Note that the actions for most of these targets are in the # automatically generated `.d' files. # .PHONY: clean realclean clean_prof_files clean_prof_files: -rm -f Prof.CallPair Prof.Counts Prof.Decl Prof.MemWords Prof.MemCells # The `clean' and `realclean' targets are implemented via `clean_local' # and `realclean_local'. This allows a user to add rules in their # Mmakefile to do a recursive mmake clean, for example, while still being # able to use the local versions in their original form. .PHONY: clean_local realclean_local realclean: realclean_local clean: clean_local realclean_local: clean_local clean_local: clean_prof_files #-----------------------------------------------------------------------------# # # Targets for building and installing libraries. # # Note: the `lib%.install_ints' rule is generated in each module's `.dep' # file so it can be more easily customised based on the desired level of # intermodule optimisation. Likewise the `lib%.install_grade_hdrs' is also # generated in the `.dep' file, since it depends on the setting of # the `--high-level-code' option. .PHONY: lib%.install lib%.install: lib%.install_ints lib%.install_hdrs lib%.install_library $(MMAKE) lib$*.install_grades .PHONY: lib%.install_grade_init lib%.install_grade_init: %.init install_grade_dirs $(INSTALL) `vpath_find $*.init` $(INSTALL_GRADE_MODULE_DIR) .PHONY: lib%.install_library lib%.install_library: lib%.$A lib%.$(EXT_FOR_SHARED_LIB) \ install_grade_dirs lib%.install_grade_hdrs \ lib%.install_opts lib%.install_grade_init $(INSTALL) `vpath_find lib$*.$A lib$*.$(EXT_FOR_SHARED_LIB)` \ $(INSTALL_MERC_LIB_DIR) $(RANLIB) $(RANLIBFLAGS) $(INSTALL_MERC_LIB_DIR)/lib$*.$A # XXX grade_files only contains the files for the default grade, not the # current grade in each iteration of the loop over ALL_LIBGRADES below. lib%.install_grades: rm -rf tmp_dir && \ mkdir tmp_dir && \ grade_files="$(foreach mve,$(GRADE_SUBDIR_MVEXTS),$($*.$(mve)))" && \ for file in x $$grade_files; do \ if test "$$file" != "x"; then \ mv -f $$file tmp_dir > /dev/null 2>&1; \ true; \ fi; \ done && \ { mv -f $(deps_subdir)$*.dep $(deps_subdir)$*.dv \ *.$A *.$(EXT_FOR_SHARED_LIB) tmp_dir || true; } && \ for grade in $(ALL_LIBGRADES); do \ if test "$$grade" != "$(GRADE)"; then \ $(MMAKE) GRADE=$$grade $*.depend || \ exit 1; \ $(MMAKE) GRADE=$$grade lib$*.install_library || \ exit 1; \ for file in x $$grade_files; do \ if test "$$file" != "x"; then \ rm -f $$file; \ fi; \ done; \ rm -f $(deps_subdir)$*.dep $(deps_subdir)$*.dv \ *.$A *.$(EXT_FOR_SHARED_LIB); \ fi; \ done && \ for file in x $$grade_files; do \ if test "$$file" != "x"; then \ mv -f tmp_dir/`basename $$file` $$file > /dev/null 2>&1; \ true; \ fi; \ done && \ { mv -f tmp_dir/*.dep tmp_dir/*.dv $(deps_subdir).; \ mv -f tmp_dir/* .; rmdir tmp_dir; true; } .PHONY: install_lib_dirs install_lib_dirs: -test -d $(INSTALL_INT_DIR) || $(INSTALL_MKDIR) $(INSTALL_INT_DIR) -test -d $(INSTALL_INC_DIR) || $(INSTALL_MKDIR) $(INSTALL_INC_DIR) -test -d $(INSTALL_MODULE_DIR) || \ $(INSTALL_MKDIR) $(INSTALL_MODULE_DIR) # The following is needed to support the `--use-subdirs' option. -test -d $(INSTALL_INT_DIR)/Mercury || \ $(INSTALL_MKDIR) $(INSTALL_INT_DIR)/Mercury .PHONY: install_grade_dirs install_grade_dirs: #install_lib_dirs -test -d $(INSTALL_MERC_LIB_DIR) || \ $(INSTALL_MKDIR) $(INSTALL_MERC_LIB_DIR) -test -d $(INSTALL_GRADE_INC_DIR) || \ $(INSTALL_MKDIR) $(INSTALL_GRADE_INC_DIR) -test -d $(INSTALL_GRADE_INT_DIR) || \ $(INSTALL_MKDIR) $(INSTALL_GRADE_INT_DIR) -test -d $(INSTALL_GRADE_MODULE_DIR) || \ $(INSTALL_MKDIR) $(INSTALL_GRADE_MODULE_DIR) # The following is needed to support the `--use-subdirs' option. # XXX Why? Grade-specific directories should not need *additional* # non-grade-specific subdirs. -test -d $(INSTALL_GRADE_INC_DIR)/Mercury || \ $(INSTALL_MKDIR) $(INSTALL_GRADE_INC_DIR)/Mercury -test -d $(INSTALL_GRADE_INT_DIR)/Mercury || \ $(INSTALL_MKDIR) $(INSTALL_GRADE_INT_DIR)/Mercury