#-----------------------------------------------------------------------------# # Copyright (C) 1997-2006 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. #-----------------------------------------------------------------------------# # library/Mmake - this is the main part of the Makefile # for building the Mercury libraries. #-----------------------------------------------------------------------------# # These need to be defined before we include Mmake.common, # so that they can be overridden in Mmake.params. EXTRA_LDFLAGS = EXTRA_LDLIBS = #-----------------------------------------------------------------------------# # Specify which files to check for namespace cleanliness, and which name # prefixes are allowed. CHECK_HDRS = CHECK_MHDRS = $(mer_std.mhs) CHECK_OBJS = $(mer_std.os) ALLOW_LIB_PREFIX=yes ALLOW_BROWSER_PREFIX=no ALLOW_MDBCOMP_PREFIX=no MERCURY_DIR=.. LINK_RUNTIME_ONLY=yes include $(MERCURY_DIR)/Mmake.common -include Mmake.library.params # Override the default rule in `mmake --use-mmc-make' that asks `mmc' to # create a missing optional params file. Mmake.library.params: # Module-specific options should go in Mercury.options so they # can be found by `mmc --make'. include Mercury.options MERCURY_MAIN_MODULES = mer_std MAIN_TARGET=all VPATH=. #-----------------------------------------------------------------------------# # Specify which options to use to compile the library. # Don't change these without good reason - if you want to do a temporary # change, change ../Mmake.params, or create Mmake.library.params. ifeq ($(LIBRARY_INTERMODULE),yes) # XXX Smart recompilation doesn't work with `--intermodule-optimization'. # We still want to generate version numbers in the interface files, so # just disable the warnings in INTER_FLAGS. # If you want to actually check termination for the library, then you need # to add --check-termination to INTER_FLAGS, but that is not enabled by default # because it probably just results in spurious warnings. # A different flags file is used when `--use-mmc-make' is in effect as # some options are (currently) incompatible with `mmc --make'. ifeq ($(MMAKE_USE_MMC_MAKE),yes) INTER_FLAGS = --flags INTER_FLAGS_MMC_MAKE else INTER_FLAGS = --flags INTER_FLAGS endif else INTER_FLAGS = endif # We compile the files in the library directory with --trace minimum by # default (set in FLAGS), which has no effect in non-debugging grades and # causes the library to be shallow traced, not deep traced, in debugging # grades. This is probably what most users want, and it makes it much easier to # maintain the expected output of the debugging test cases in debugging grades. # However, this can be overridden by setting LIBRARY_TRACE_MINIMUM to no. # # Always generate dependencies for use by `mmc --make'. ifeq ($(LIBRARY_TRACE_MINIMUM),no) LIBRARY_TRACE_LEVEL = --trace default else LIBRARY_TRACE_LEVEL = endif # We need to compile the library with --strict-sequential for two reasons: # (1) Otherwise Mercury code that is compiled with --strict-sequential # might do the wrong thing, because the standard library wasn't compiled # with --strict-sequential. (We could make it a separate grade, but # that's not worth it.) # (2) The code for get_determinism in library/exception.m relies on it # (in particular it relies on --no-reorder-disj). MCFLAGS += --flags LIB_FLAGS $(CONFIG_OVERRIDE) MCFLAGS += $(LIBRARY_TRACE_LEVEL) $(INTER_FLAGS) # The IL and Java implementations of the standard library are not yet complete, # so we need to pass `--allow-stubs' to get them to compile. # Since the standard library is compiled with `--halt-at-warn', # we also need `--no-warn-stubs'. ifneq ("$(filter il% java%,$(GRADE))","") MCFLAGS += --allow-stubs --no-warn-stubs endif #-----------------------------------------------------------------------------# CFLAGS += $(DLL_CFLAGS) ifeq ($(INSTALLABLE_PREFIX),yes) MLFLAGS += -R$(FINAL_INSTALL_MERC_LIB_DIR) \ -R$(FINAL_INSTALL_MERC_GC_LIB_DIR) MCFLAGS += -R$(FINAL_INSTALL_MERC_LIB_DIR) \ -R$(FINAL_INSTALL_MERC_GC_LIB_DIR) endif MTAGS = $(SCRIPTS_DIR)/mtags LN = ln #-----------------------------------------------------------------------------# # Set the install name for Darwin shared libraries. We disable the # --shlib-linker-use-install-name mmc option so that the -install_name linker # option is not passed in the .dep files. We do this to avoid a problem when # building from the C source distribution: if the C source distribution is # generated on a non-Darwin system then the -install_name option is not passed # in the .dep files, so it must be passed here, however if a C source # distribution is generated on a Darwin system then by default the # -install_name option will be passed in the .dep files which will cause it to # be passed twice (here and in the .dep files) which is not allowed by the # linker, so we disable the mmc option which causes the -install_name option # to be passed in the .dep files. LD_LIBFLAGS-libmer_std.dylib = -install_name \ $(FINAL_INSTALL_MERC_LIB_DIR)/libmer_std.dylib #-----------------------------------------------------------------------------# # Stuff for Windows DLLS using gnu-win32 ifeq ($(USE_DLLS),yes) DLL_CFLAGS = -Dlib$(STD_LIB_NAME)_DEFINE_DLL include $(MERCURY_DIR)/Makefile.DLLs else DLL_CFLAGS = DLL_DEF_LIB = endif #-----------------------------------------------------------------------------# # targets .PHONY: all all: mercury all-ints $(TAGS_FILE_EXISTS) .PHONY: mercury mercury: lib_std #-----------------------------------------------------------------------------# .PHONY: depend depend: LIB_FLAGS $(STD_LIB_NAME).depend .PHONY: check check: $(STD_LIB_NAME).check .PHONY: all-ints ifeq ($(LIBRARY_INTERMODULE),yes) all-ints: ints int3s opts trans_opts else all-ints: ints int3s endif .PHONY: ints ints: $(STD_LIB_NAME).ints .PHONY: int3s int3s: $(STD_LIB_NAME).int3s .PHONY: opts opts: $(STD_LIB_NAME).opts .PHONY: trans_opts trans_opts: $(STD_LIB_NAME).trans_opts $(STD_LIB_NAME).trans_opts: $($(STD_LIB_NAME).trans_opts) #-----------------------------------------------------------------------------# tags: $(MTAGS) $($(STD_LIB_NAME).ms) $(MTAGS) $($(STD_LIB_NAME).ms) .PHONY: tags_file_exists tags_file_exists: @if test ! -f tags; then echo making tags ; \ $(MTAGS) $($(STD_LIB_NAME).ms) ; fi $(STD_LIB_NAME).stats: $(COMPILER_DIR)/source_stats.awk $($(STD_LIB_NAME).ms) awk -f $(COMPILER_DIR)/source_stats.awk \ `vpath_find $($(STD_LIB_NAME).ms)` > $@ #-----------------------------------------------------------------------------# .PHONY: dates dates: touch $($(STD_LIB_NAME).dates) #-----------------------------------------------------------------------------# # Note that we need to explicitly mention $($(STD_LIB_NAME).pic_ss) somewhere # in the Mmakefile, otherwise it won't build properly with --target asm: # GNU Make's pattern rule algorithm will try to use the .m -> .c -> .pic_o # rule chain rather than the .m -> .pic_s_date -> .pic_s -> .pic_o chain. # So don't remove the pic_ss target here. .PHONY: os cs ss pic_ss ils ifneq ($(MMAKE_USE_MMC_MAKE),yes) os: $($(STD_LIB_NAME).os) cs: $($(STD_LIB_NAME).cs) ss: $($(STD_LIB_NAME).ss) pic_ss: $($(STD_LIB_NAME).pic_ss) ils: $($(STD_LIB_NAME).ils) javas: $($(STD_LIB_NAME).javas) else os: $(STD_LIB_NAME).os cs: $(STD_LIB_NAME).cs ss: $(STD_LIB_NAME).ss pic_ss: $(STD_LIB_NAME).pic_ss ils: $(STD_LIB_NAME).ils javas: $(STD_LIB_NAME).javas endif # The names `int', `float', and `char' can't be used as class names, # because they are Java keywords. So we use `mr_int', `mr_float', and # `mr_char' instead. `enum' is also a keyword in Java 1.5, so we # likewise use `mr_enum'. Since Java implementations often assume that # a class foo is located in a file foo.java, we similarly mangle the # Java file names for these standard library modules. JAVAS = ` echo $($(STD_LIB_NAME).javas) | sed \ -e 's/ int.java/ mr_int.java/' \ -e 's/ float.java/ mr_float.java/' \ -e 's/ char.java/ mr_char.java/' \ -e 's/ enum.java/ mr_enum.java/' ` # We need to invoke javac on all of the classes at the same time, # rather than compiling them separately. This is needed because # otherwise javac doesn't handle cyclic dependencies between different # modules. classes: javas java_symlinks $(JAVAC) $(JAVACFLAGS) $(JAVAS) # javac expects to find the sources for symbols named mercury.* in # files mercury/*, and likewise for symbols named mercury.runtime.* # in mercury/runtime/*. But in our sources, those symbols actually # come from this directory (library/*) and from java/runtime/*, # respectively. So we set up some symbolic links to help # javac find the way to the sources. .PHONY: java_symlinks java_symlinks: [ -d mercury ] || ln -s . mercury [ -d runtime ] || ln -s $(MERCURY_DIR)/java/runtime . # Once all of the library classes have been compiled, we put them in a single # jar file. At this point we also add the runtime classes to a jar file. # Note that this stage makes use of the symbolic links created earlier to # ensure that the path names are correct within the jar files. # We also compile NATIVE_SO here and copy it into the library directory. JARS = $(STD_LIB_NAME).jar $(RT_LIB_NAME).jar # We ignore the exit status of the last two commands because NATIVE_SO is not # an essential part of the Mercury standard library for the Java # implementation. Users should be able to run programs in grade Java without # any architecture-specific objects. .PHONY: jars jars: classes $(JAR) $(JAR_CREATE_FLAGS) $(STD_LIB_NAME).jar mercury/*.class $(JAR) $(JAR_CREATE_FLAGS) $(RT_LIB_NAME).jar mercury/runtime/*.class -+cd mercury/runtime && mmake $(NATIVE_SO) -cp mercury/runtime/$(NATIVE_SO) . # This shared object is needed to run some of the standard library methods. NATIVE_SO = Native.$(EXT_FOR_SHARED_LIB) #-----------------------------------------------------------------------------# .PHONY: lib_std # The ilc and il grades target Microsoft's .NET frameworks. ifeq ($(findstring il,$(GRADE)),il) lib_std: mercury.dll lib$(STD_LIB_NAME) # We have to hardcode the names of the runtime DLL files. RUNTIME_DLLS=mercury_dotnet.dll mercury_il.dll # -AI sets the assembly search path (just like -I for assemblies) MS_CLFLAGS = -AI`$(FIX_PATH_FOR_CL) $(RUNTIME_DIR)` -I`$(FIX_PATH_FOR_CL) $(RUNTIME_DIR)` # For some reason, using /clr:noAssembly results in a link error when # building io__cpp_code.dll, because it doesn't link in the native library # needed for putenv(). So we need to use /link /noassembly instead. # MS_CL_NOASM=:noAssembly MS_CL_LIBS=/link /noassembly MS_CSCFLAGS=/t:module # If you do generate a new strong name, you had better update # compiler/mlds_to_il.m to generate references to it. It is also hard-coded # in runtime/mercury_il.il. # This is hard-coding is sub-optimal -- the compiler should automatically find # out what the strong name is. library_strong_name.sn: sn -k library_strong_name.sn mercury.dll: $($(STD_LIB_NAME).dlls) $($(STD_LIB_NAME).foreign_dlls) \ $(RUNTIME_DLLS) library_strong_name.sn $(MS_AL) -v:0.0.0.0 -keyf:library_strong_name.sn -out:mercury.dll \ $($(STD_LIB_NAME).dlls) $($(STD_LIB_NAME).foreign_dlls) \ $(RUNTIME_DLLS) # This is useful for running PEverify on the library. # For multi-file assemblies, PEverify only works on executables, # not on libraries. mercury_exe.exe: $($(STD_LIB_NAME).dlls) $($(STD_LIB_NAME).foreign_dlls) \ $(RUNTIME_DLLS) library_strong_name.sn $(MS_AL) -v:0.0.0.0 -keyf:library_strong_name.sn -out:mercury_exe.exe \ $($(STD_LIB_NAME).dlls) $($(STD_LIB_NAME).foreign_dlls) \ $(RUNTIME_DLLS) # The runtime DLLs must be copied into this directory from the runtime # directory so they can be installed properly. .PHONY: copy_runtime_dlls copy_runtime_dlls: $(RUNTIME_DLLS) mercury_il.dll: ../runtime/mercury_il.dll cp ../runtime/mercury_il.dll . mercury_dotnet.dll: ../runtime/mercury_dotnet.dll cp ../runtime/mercury_dotnet.dll . CSHARP_MODULES = array builtin char construct dir exception float int io \ library math private_builtin rtti_implementation std_util \ string time type_desc CSHARP_DLLS = $(CSHARP_MODULES:%=%__csharp_code.dll) $(CSHARP_DLLS) : $(RUNTIME_DLLS) endif #-----------------------------------------------------------------------------# ifeq ("$(findstring java,$(GRADE))","java") lib_std: jars endif #-----------------------------------------------------------------------------# # # Some extra rules that we need for the C and asm back-ends # ifeq ("$(findstring il,$(GRADE))$(findstring java,$(GRADE))","") # The following dependency is just there to improve compilation speed; # making tree234.$O first improves effective parallelism with parallel makes. # `mmc --make' does not support parallel makes, so this dependency just # slows things down. ifneq ($(MMAKE_USE_MMC_MAKE),yes) lib_std: $(os_subdir)tree234.$O endif lib_std: lib$(STD_LIB_NAME) ifneq ($(MMAKE_USE_MMC_MAKE),yes) EXTRA_INIT_COMMAND = ./print_extra_inits $($(STD_LIB_NAME).ms) else MCFLAGS += --extra-init-command ./print_extra_inits endif endif # GRADE != il && GRADE != java #-----------------------------------------------------------------------------# # Rebuild all the object files if the configuration macros or VERSION # have changed. Only some source files use the configuration macros, # but these uses may leak into other object files with inter-module # optimization. $(mer_std.os): $(RUNTIME_DIR)/mercury_conf.h # The object files in this directory depend on many of the header files # in the runtime. However, changes to many of these header files require # a global make clean. Here we list only the header files from the runtime # whose changes don't usually require a make clean but which nevertheless # require some files in the library to be recompiled. $(os_subdir)benchmarking.$O \ $(os_subdir)benchmarking.pic_o \ $(os_subdir)construct.$O \ $(os_subdir)construct.pic_o \ $(os_subdir)deconstruct.$O \ $(os_subdir)deconstruct.pic_o \ $(os_subdir)std_util.$O \ $(os_subdir)std_util.pic_o \ : ../runtime/mercury_stack_layout.h $(os_subdir)deconstruct.$O \ $(os_subdir)deconstruct.pic_o \ $(os_subdir)std_util.$O \ $(os_subdir)std_util.pic_o \ : ../runtime/mercury_ml_functor_body.h \ ../runtime/mercury_ml_arg_body.h \ ../runtime/mercury_ml_deconstruct_body.h \ ../runtime/mercury_deconstruct_macros.h \ ../runtime/mercury_deconstruct.h $(os_subdir)construct.$O \ $(os_subdir)construct.pic_o \ $(os_subdir)std_util.$O \ $(os_subdir)std_util.pic_o \ : ../runtime/mercury_construct.h $(os_subdir)type_desc.$O \ $(os_subdir)type_desc.pic_o \ $(os_subdir)std_util.$O \ $(os_subdir)std_util.pic_o \ : ../runtime/mercury_type_desc.h $(os_subdir)table_builtin.$O \ $(os_subdir)table_builtin.pic_o \ : ../runtime/mercury_tabling_macros.h \ ../runtime/mercury_tabling_preds.h \ ../runtime/mercury_minimal_model.h #-----------------------------------------------------------------------------# # In the past we generated liblibrary.* and then linked # libmer_std.* to the files. realclean_local: rm -f mercury_dotnet.dll mercury_il.dll rm -f liblibrary.$A liblibrary.so library.init rm -f $($(STD_LIB_NAME).mods:%=%.h) rm -f tags LIB_FLAGS LIB_FLAGS.date rm -f mercury runtime rm -f mr_int.class mr_float.class mr_char.class rm -f mr_int\$$*.class mr_float\$$*.class mr_char\$$*.class rm -f $(JARS) $(NATIVE_SO) #-----------------------------------------------------------------------------# ifeq ($(LIBRARY_INTERMODULE),yes) # Installation targets # LIBRARY_INTERMODULE should be turned off only during development. # A full install requires the library's .opt and .trans_opt files. # If you add a new target below, please add a parallel target for the # case LIBRARY_INTERMODULE != yes. .PHONY: install install: install_mercury .PHONY: install_all install_all: install_mercury ifneq ($(MMAKE_USE_MMC_MAKE),yes) .PHONY: install_mercury install_mercury: install_ints install_hdrs install_init install_library .PHONY: install_ints install_ints: lib$(STD_LIB_NAME).install_ints .PHONY: install_hdrs install_hdrs: lib$(STD_LIB_NAME).install_hdrs .PHONY: install_init install_init: $(STD_LIB_NAME).init install_lib_dirs cp `vpath_find $(STD_LIB_NAME).init` $(INSTALL_MODULE_DIR) # "$(STD_LIB_NAME).init" used to be called "library.init" or # "libmercury.init". If there is still a version with an old name # lying around, then delete it; otherwise the initialization # would get done twice. rm -f $(INSTALL_MODULE_DIR)/library.init \ $(INSTALL_MODULE_DIR)/libmercury.init ifneq (,$(findstring il,$(GRADE))) # XXX some modules in the browser directory need library.int3 .PHONY: install_library install_library: mercury.dll install_grade_dirs install_gac \ install_strong_name lib$(STD_LIB_NAME).install_grade_hdrs \ lib$(STD_LIB_NAME).install_opts cp `vpath_find $($(STD_LIB_NAME).foreign_dlls) $($(STD_LIB_NAME).dlls) \ mercury.dll` $(INSTALL_MERC_LIB_DIR) # To build the .NET library with debugging information, add # the following to ../Mmake.params: # # EXTRA_MS_ILASMFLAGS=/debug # EXTRA_MS_CSCFLAGS=/debug+ /debug:full # EXTRA_MS_CLFLAGS=/Zi # # XXX Unfortunately, however, this is a problem with AL, which prohibits # linking debuggable C# code with IL or MC++ code. The following # horrible hack avoids that problem. After modifying Mmake.params as # described above, invoke `mmake install_debug_library'. .PHONY: install_debug_library install_debug_library: -$(MMAKE) $(MMAKEFLAGS) $(MMAKE) $(MMAKEFLAGS) munge_dll_debug_info $(MMAKE) $(MMAKEFLAGS) install_library # The GAC is the global assembly cache, which is the system managed # place to put .NET assemblies. # gacutil installs (and uninstalls) DLLs from the GAC. .PHONY: install_gac install_gac: mercury.dll gacutil -i mercury.dll .PHONY: install_strong_name install_strong_name: library_strong_name.sn cp `vpath_find library_strong_name.sn` \ $(INSTALL_MERC_LIB_DIR)/mercury.sn else ifneq (,$(findstring java,$(GRADE))) # Copy the jars and NATIVE_SO to INSTALL_JAVA_LIBRARY_DIR. Ignore the exit # status of last command, since NATIVE_SO may not be available and is not # essential. .PHONY: install_library install_library: jars mkdir -p $(INSTALL_JAVA_LIBRARY_DIR) cp $(JARS) $(INSTALL_JAVA_LIBRARY_DIR) -cp $(NATIVE_SO) $(INSTALL_JAVA_LIBRARY_DIR) else # we depend on lib$(STD_LIB_NAME) because lib$(STD_LIB_NAME).install_library # doesn't make library.int3, but some modules in the browser directory need it. .PHONY: install_library install_library: lib$(STD_LIB_NAME) lib$(STD_LIB_NAME).install_library endif #ifneq (,$(findstring java,$(GRADE))) endif #ifneq (,$(findstring il,$(GRADE))) # $(STD_LIB_NAME).split.$A is a version of lib$(STD_LIB_NAME).$A # that has been compiled with `--split-c-files'. .PHONY: install_split_library install_split_library: lib$(STD_LIB_NAME).install_split_library else #ifneq ($(MMAKE_USE_MMC_MAKE),yes) # Prevent `mmc --make' from installing the default set of grades for # `libFOO.install' targets. MCFLAGS += --no-libgrade .PHONY: install_mercury install_mercury: lib$(STD_LIB_NAME).install .PHONY: install_library install_library: lib$(STD_LIB_NAME).install endif #ifneq ($(MMAKE_USE_MMC_MAKE),yes) else .PHONY: install install: echo "Can't do make install without LIBRARY_INTERMODULE=yes" exit 1 .PHONY: install_all install_all: echo "Can't do make install without LIBRARY_INTERMODULE=yes" exit 1 .PHONY: install_mercury install_mercury: echo "Can't do make install without LIBRARY_INTERMODULE=yes" exit 1 .PHONY: install_ints install_ints: echo "Can't do make install without LIBRARY_INTERMODULE=yes" exit 1 .PHONY: install_hdrs install_hdrs: echo "Can't do make install without LIBRARY_INTERMODULE=yes" exit 1 .PHONY: install_init install_init: echo "Can't do make install without LIBRARY_INTERMODULE=yes" exit 1 .PHONY: install_library install_library: echo "Can't do make install without LIBRARY_INTERMODULE=yes" exit 1 .PHONY: install_split_library install_split_library: echo "Can't do make install without LIBRARY_INTERMODULE=yes" exit 1 endif .PHONY: munge_dll_debug_info munge_dll_debug_info: for file in *csharp_code.dll; do \ ildasm /out:$$file.ild $$file; \ sed 's/01 00 00 01/01 00 01 01/' $$file.ild \ > $$file.ild.munged; \ ilasm /quiet /dll /debug /out:$$file $$file.ild.munged; \ done #-----------------------------------------------------------------------------#