#-----------------------------------------------------------------------------# # Copyright (C) 1995-2003 The University of Melbourne. # 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) #-----------------------------------------------------------------------------# # Beware that the order of suffixes is significant. .SUFFIXES: .m .nl .no .err \ .int0 .int .int2 .int3 .opt .trans_opt \ .dep .depend .dv .doit .ugly \ .date0 .date .date3 .optdate .trans_opt_date \ .c .$O .pic_o \ .i .s .pic_s \ .rlo \ .java .class \ .il .dll .exe .cpp .cs \ .c_date .il_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$(mihs_subdir). endif #-----------------------------------------------------------------------------# # # Find the directory containing the interface files for the standard library. # ifdef MERCURY_INT_DIR MERC_INT_DIR = $(MERCURY_INT_DIR) else ifdef MERCURY_STDLIB_DIR export MERCURY_STDLIB_DIR MERC_INT_DIR = $(MERCURY_STDLIB_DIR)/ints else MERC_INT_DIR = endif 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: $(il_dates_subdir)%.il_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. ifeq ($(MMAKE_USE_MMC_MAKE),no) # beware the code for `%.depend' and `%.dep'/`%.dv' is duplicated $(deps_subdir)%.dep $(deps_subdir)%.dv: $(MCD) $(ALL_GRADEFLAGS) $(ALL_MCDFLAGS) $* ifeq ($(MMAKE_USE_SUBDIRS),yes) # javac doesn't create the destination directory for class files # so we must create it manually -[ -d $(classes_subdir) ] || mkdir $(classes_subdir) # the following mkdirs work around a bug in GNU Make -[ -d Mercury/dates ] || mkdir Mercury/dates -[ -d Mercury/date0s ] || mkdir Mercury/date0s -[ -d Mercury/date3s ] || mkdir Mercury/date3s -[ -d Mercury/optdates ] || mkdir Mercury/optdates -[ -d Mercury/trans_opt_dates ] || mkdir Mercury/trans_opt_dates -[ -d Mercury/c_dates ] || mkdir Mercury/c_dates -[ -d Mercury/il_dates ] || mkdir Mercury/il_dates -[ -d Mercury/s_dates ] || mkdir Mercury/s_dates -[ -d Mercury/pic_s_dates ] || mkdir Mercury/pic_s_dates endif # beware the code for `%.depend' and `%.dep'/`%.dv' is duplicated .PHONY: %.depend %.depend : $(MCD) $(ALL_GRADEFLAGS) $(ALL_MCDFLAGS) $* ifeq ($(MMAKE_USE_SUBDIRS),yes) # javac doesn't create the destination directory for class files # so we must create it manually -[ -d $(classes_subdir) ] || mkdir $(classes_subdir) # the following mkdirs work around a bug in GNU Make -[ -d Mercury/dates ] || mkdir Mercury/dates -[ -d Mercury/date0s ] || mkdir Mercury/date0s -[ -d Mercury/date3s ] || mkdir Mercury/date3s -[ -d Mercury/optdates ] || mkdir Mercury/optdates -[ -d Mercury/trans_opt_dates ] || mkdir Mercury/trans_opt_dates -[ -d Mercury/c_dates ] || mkdir Mercury/c_dates -[ -d Mercury/il_dates ] || mkdir Mercury/il_dates -[ -d Mercury/s_dates ] || mkdir Mercury/s_dates -[ -d Mercury/pic_s_dates ] || mkdir Mercury/pic_s_dates endif endif # MMAKE_USE_MMC_MAKE == no #-----------------------------------------------------------------------------# # # Rules for building interface files # WARNING: any changes here will probably need to be # duplicated in compiler/modules.m. # ifeq ($(MMAKE_USE_MMC_MAKE), no) $(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 == no #-----------------------------------------------------------------------------# # # Rules for compiling Mercury source files # WARNING: any changes here will probably need to be # duplicated in compiler/modules.m. # ifeq ($(MMAKE_USE_MMC_MAKE), no) ifeq ($(TARGET_ASM),yes) # `--target asm' back-end # When smart recompilation finds that a module does not need to be # recompiled, it only touches the `.s_date' or `.pic_s_date' file. $(ss_subdir)%.s : $(s_dates_subdir)%.s_date @: $(pic_ss_subdir)%.pic_s : $(pic_s_dates_subdir)%.pic_s_date @: $(s_dates_subdir)%.s_date : %.m $(MCG) $(ALL_GRADEFLAGS) --target-code-only $(ALL_MCGFLAGS) \ $(*F) $(ERR_REDIRECT) $(pic_s_dates_subdir)%.pic_s_date : %.m $(MCG) $(ALL_GRADEFLAGS) --target-code-only $(ALL_MCGFLAGS) \ --pic --cflags "$(GCCFLAGS_FOR_PIC)" $(*F) $(ERR_REDIRECT) $(os_subdir)%.$O : $(ss_subdir)%.s $(AS) $< $(OBJFILE_OPT)$@ $(os_subdir)%.pic_o : $(pic_ss_subdir)%.pic_s $(AS) $< $(OBJFILE_OPT)$@ # For *__c_code.{o,pic_o}, we depend on the .s or .pic_s file rather # than the .c file, since the .c file is produced as a side-effect of # generating the .s/.pic_s file. $(os_subdir)%__c_code.$O : $(ss_subdir)%.s $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) \ -c $(cs_subdir)$*.c $(OBJFILE_OPT)$@ $(os_subdir)%__c_code.pic_o : $(pic_ss_subdir)%.pic_s $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) $(CFLAGS_FOR_PIC) \ -c $(cs_subdir)$*.c $(OBJFILE_OPT)$@ endif # 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) # Aditi-RL back-end $(rlos_subdir)%.rlo : %.m $(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) \ --aditi-only $(*F) $(ERR_REDIRECT) # Java back-end ifeq ($(MMAKE_USE_SUBDIRS),yes) $(classes_subdir)%.class: $(javas_subdir)%.java $(JAVAC) -d $(classes_subdir) $< else $(classes_subdir)%.class: $(javas_subdir)%.java $(JAVAC) $< 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) # .NET back-end # When smart recompilation finds that a module does not need to be # recompiled, it only touches the `.il_date' file. $(ils_subdir)%.il : $(il_dates_subdir)%.il_date @: $(il_dates_subdir)%.il_date : %.m $(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) \ --il-only $(*F) $(ERR_REDIRECT) # These rules are only available in *il* backends, because we'd like to avoid # processing user code that is in a .cpp file, and we'd like to avoid going via # IL to generate a DLL if we are in a non-IL grade. ifeq ($(findstring il,$(GRADE)),il) # Note that we use `-' rather than `/' as the option character for options # to $(MS_CL), to avoid confusion with Unix-style path names. # `cl' supports both variants. $(os_subdir)%.dll : %.cpp $(MS_CL) -CLR$(MS_CL_NOASM) $(ALL_MS_CLFLAGS) \ -I`$(FIX_PATH_FOR_CL) $(MERC_C_INCL_DIR)` \ -AI`$(FIX_PATH_FOR_CL) $(MERC_DLL_DIR)` $< \ -LD -o $@ $(MS_CL_LIBS) rm -f $*.obj $(os_subdir)%.dll : %.cs $(MS_CSC) /t:library /lib:`$(FIX_PATH_FOR_CSC) $(MERC_DLL_DIR)` \ /out:$@ $(CSHARP_ASSEMBLY_REFS-$*) $(ALL_MS_CSCFLAGS) $< $(os_subdir)%.dll : %.il $(MS_ILASM) $(ALL_MS_ILASMFLAGS) /dll /quiet /OUT=$@ $< mercury.sn: cp $(MERC_DLL_DIR)/mercury.sn . endif # The `touch' is necessary, since otherwise if # the old .err file was of size zero and # the new .err file is also of size zero, # the time-stamp doesn't get updated! # (Is that a bug in unix? In bash?) .m.err: $(MCE) $(ALL_MCFLAGS) $(*F) $(ERR_REDIRECT) @touch $@ endif # MMAKE_USE_MMC_MAKE == no .m.ugly: $(MC) --convert-to-mercury $(ALL_MCFLAGS) $(*F) #-----------------------------------------------------------------------------# # # Rules for compiling C files in the user's source directory. # .c.$O: $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) -c $< $(OBJFILE_OPT)$@ .c.pic_o: $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) $(CFLAGS_FOR_PIC) \ -c $< $(OBJFILE_OPT)$@ .c.s: $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) -S $< -o $@ .c.pic_s: $(MGNUC) $(ALL_GRADEFLAGS) $(ALL_MGNUCFLAGS) $(CFLAGS_FOR_PIC) \ -S $< -o $@ .c.i: $(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. # ifeq ($(MMAKE_USE_MMC_MAKE),no) 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) == no #-----------------------------------------------------------------------------# # # Rules for compiling IL files in the user's source directory. # 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 il or cpp files of their own which need to be # compiled. # # To avoid possible problems with invoking these commands unintentionally, # we only activate these rules when in an IL grade. # ifeq ($(findstring il,$(GRADE)),il) .il.dll: $(MS_ILASM) $(ALL_MS_ILASMFLAGS) /dll /quiet /OUT=$@ $< .il.exe: $(MS_ILASM) $(ALL_MS_ILASMFLAGS) /quiet /OUT=$@ $< .cpp.dll: $(MS_CL) -CLR$(MS_CL_NOASM) $(ALL_MS_CLFLAGS) \ -I`$(FIX_PATH_FOR_CL) $(MERC_C_INCL_DIR)` \ -AI`$(FIX_PATH_FOR_CL) $(MERC_DLL_DIR)` $< \ -LD -o $@ $(MS_CL_LIBS) rm -f $*.obj .cs.dll: $(MS_CSC) /t:library /lib:`$(FIX_PATH_FOR_CSC) $(MERC_DLL_DIR)` \ /out:$@ $(CSHARP_ASSEMBLY_REFS-$*) $(EXTRA_CSCFLAGS) $< .cpp.exe: $(MS_CL) -CLR$(MS_CL_NOASM) -I$(MERCURY_LIBRARY_PATH) $< -link -entry:main $(MS_CL_LIBS) -out:$@ .cs.exe: $(MS_CSC) /lib:`$(FIX_PATH_FOR_CSC) $(MERC_DLL_DIR)` /out:$@ \ $(CSHARP_ASSEMBLY_REFS-$*) $(EXTRA_CSCFLAGS) $< endif # $(findstring il,$(GRADE)) != "" #-----------------------------------------------------------------------------# 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) %.err: $(MCM) $@ # If we don't know how to make the file, try using `mmc --make'. .DEFAULT: $(MCM) $@ clean_local: $(MERCURY_MAIN_MODULES:%=%.clean) realclean_local: $(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_init \ lib%.install_library $(MMAKE) lib$*.install_grades || { mercury_cleanup_install && exit 1; } .PHONY: lib%.install_split lib%.install_split: lib%.install_ints lib%.install_init \ lib%.install_split_library $(MMAKE) lib$*.install_split_grades || \ { mercury_cleanup_install && exit 1; } .PHONY: lib%.install_init lib%.install_init: %.init install_lib_dirs $(INSTALL) `vpath_find $*.init` $(INSTALL_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 $(INSTALL) `vpath_find lib$*.$A lib$*.$(EXT_FOR_SHARED_LIB)` \ $(INSTALL_MERC_LIB_DIR) $(RANLIB) $(INSTALL_MERC_LIB_DIR)/lib$*.$A lib%.install_split_library: %.split.$A install_grade_dirs $(INSTALL) `vpath_find $*.split.$A` $(INSTALL_MERC_LIB_DIR)/lib$*.$A $(RANLIB) $(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 ext,$(GRADE_SUBDIR_EXTS),$($*.$(ext)s))" && \ for file in x $$grade_files; do \ if [ "$$file" != "x" ]; then \ mv -f $$file tmp_dir > /dev/null 2>&1; \ true; \ fi; \ done && \ { mv -f $(deps_subdir)$*.dep $(deps_subdir)$*.dv \ *.a *.so tmp_dir || true; } && \ for grade in $(ALL_LIBGRADES); do \ if [ "$$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 [ "$$file" != "x" ]; then \ rm -f $$file; \ fi; \ done; \ rm -f $(deps_subdir)$*.dep $(deps_subdir)$*.dv \ *.a *.so; \ fi; \ done && \ for file in x $$grade_files; do \ if [ "$$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; } lib%.install_split_grades: rm -rf tmp_dir && \ mkdir tmp_dir && \ { mv -f $(deps_subdir)$*.dep $(deps_subdir)$*.dv $($*.mihs) \ $($*.dirs) *.a *.so tmp_dir || true; } && \ for grade in $(ALL_LIBGRADES); do \ if [ "$$grade" != "$(GRADE)" ]; then \ $(MMAKE) GRADE=$$grade $*.depend || \ exit 1; \ $(MMAKE) GRADE=$$grade lib$*.install_split_library || \ exit 1; \ rm -rf $(deps_subdir)$*.dep $(deps_subdir)$*.dv \ $($*.mihs) $($*.dirs) *.a *.so; \ fi; \ done && \ { mv tmp_dir/*.dir $(dirs_subdir). ; \ mv tmp_dir/*.dep $(deps_subdir). ; \ mv tmp_dir/*.dv $(deps_subdir). ; \ mv tmp_dir/* . ; rmdir tmp_dir ; true; } .PHONY: install_lib_dirs install_lib_dirs: -[ -d $(INSTALL_INT_DIR) ] || $(INSTALL_MKDIR) $(INSTALL_INT_DIR) -[ -d $(INSTALL_INC_DIR) ] || $(INSTALL_MKDIR) $(INSTALL_INC_DIR) -[ -d $(INSTALL_MODULE_DIR) ] || $(INSTALL_MKDIR) $(INSTALL_MODULE_DIR) # The following is needed to support the `--use-subdirs' option -[ -d $(INSTALL_INT_DIR)/Mercury ] || \ $(INSTALL_MKDIR) $(INSTALL_INT_DIR)/Mercury .PHONY: install_grade_dirs install_grade_dirs: #install_lib_dirs -[ -d $(INSTALL_MERC_LIB_DIR) ] || \ $(INSTALL_MKDIR) $(INSTALL_MERC_LIB_DIR) -[ -d $(INSTALL_GRADE_INC_DIR) ] || \ $(INSTALL_MKDIR) $(INSTALL_GRADE_INC_DIR) -[ -d $(INSTALL_GRADE_INT_DIR) ] || \ $(INSTALL_MKDIR) $(INSTALL_GRADE_INT_DIR) # The following is needed to support the `--use-subdirs' option -[ -d $(INSTALL_GRADE_INC_DIR)/Mercury ] || \ $(INSTALL_MKDIR) $(INSTALL_GRADE_INC_DIR)/Mercury -[ -d $(INSTALL_GRADE_INT_DIR)/Mercury ] || \ $(INSTALL_MKDIR) $(INSTALL_GRADE_INT_DIR)/Mercury #-----------------------------------------------------------------------------#