-- -- make_cpp.lua -- Generate a C/C++ project makefile. -- Copyright (c) 2002-2009 Jason Perkins and the Premake project -- premake.make.cpp = { } local _ = premake.make.cpp function premake.make_cpp(prj) -- create a shortcut to the compiler interface local cc = premake.gettool(prj) -- build a list of supported target platforms that also includes a generic build local platforms = premake.filterplatforms(prj.solution, cc.platforms, "Native") premake.gmake_cpp_header(prj, cc, platforms) for _, platform in ipairs(platforms) do for cfg in premake.eachconfig(prj, platform) do premake.gmake_cpp_config(cfg, cc) end end -- list intermediate files _p('OBJECTS := \\') for _, file in ipairs(prj.files) do if path.iscppfile(file) or path.getextension(file) == ".asm" then _p('\t$(OBJDIR)/%s.o \\', _MAKE.esc(path.getbasename(file))) end end _p('') _p('RESOURCES := \\') for _, file in ipairs(prj.files) do if path.isresourcefile(file) then _p('\t$(OBJDIR)/%s.res \\', _MAKE.esc(path.getbasename(file))) end end _p('') -- identify the shell type _p('SHELLTYPE := msdos') _p('ifeq (,$(ComSpec)$(COMSPEC))') _p(' SHELLTYPE := posix') _p('endif') _p('ifeq (/bin,$(findstring /bin,$(SHELL)))') _p(' SHELLTYPE := posix') _p('endif') _p('') -- main build rule(s) _p('.PHONY: clean prebuild prelink') _p('') if os.is("MacOSX") and prj.kind == "WindowedApp" then _p('all: $(TARGET) $(dir $(TARGETDIR))PkgInfo $(dir $(TARGETDIR))Info.plist') else _p('all: $(TARGET)') end _p('\t@:') _p('') -- target build rule _p('$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES) | prelink') _p('\t@echo Linking %s', prj.name) _p('\t$(SILENT) $(LINKCMD)') _p('\t$(POSTBUILDCMDS)') _p('') -- Create destination directories. Can't use $@ for this because it loses the -- escaping, causing issues with spaces and parenthesis _p('$(TARGETDIR):') premake.make_mkdirrule("$(TARGETDIR)") _p('$(OBJDIR):') premake.make_mkdirrule("$(OBJDIR)") -- Mac OS X specific targets if os.is("MacOSX") and prj.kind == "WindowedApp" then _p('$(dir $(TARGETDIR))PkgInfo:') _p('$(dir $(TARGETDIR))Info.plist:') _p('') end -- clean target _p('clean:') _p('\t@echo Cleaning %s', prj.name) _p('ifeq (posix,$(SHELLTYPE))') _p('\t$(SILENT) rm -f $(TARGET)') _p('\t$(SILENT) rm -rf $(OBJDIR)') _p('else') _p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGET)) del $(subst /,\\\\,$(TARGET))') _p('\t$(SILENT) if exist $(subst /,\\\\,$(OBJDIR)) rmdir /s /q $(subst /,\\\\,$(OBJDIR))') _p('endif') _p('') -- custom build step targets _p('prebuild: $(TARGETDIR) $(OBJDIR)') _p('\t$(PREBUILDCMDS)') _p('') _p('prelink:') _p('\t$(PRELINKCMDS)') _p('') -- precompiler header rule _.pchrules(prj) -- per-file rules for _, file in ipairs(prj.files) do if path.iscppfile(file) then -- Don't use PCH for Obj-C/C++ files (we could but we'd have to compile them separately -- and there's no advantage to that yet) local gchobj = '$(GCH)' local pchincludes = '$(PCHINCLUDES)' if (path.getextension(file) == ".mm" or path.getextension(file) == ".m") then gchobj = '' pchincludes = '' end _p('$(OBJDIR)/%s.o: %s %s | prebuild', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file), gchobj) _p('\t@echo $(notdir $<)') if (path.iscfile(file)) then _p('\t$(SILENT) $(CC) %s $(CFLAGS) -MF $(OBJDIR)/%s.d -MT "$@" -o "$@" -c "$<"', pchincludes, _MAKE.esc(path.getbasename(file))) else _p('\t$(SILENT) $(CXX) %s $(CXXFLAGS) -MF $(OBJDIR)/%s.d -MT "$@" -o "$@" -c "$<"', pchincludes, _MAKE.esc(path.getbasename(file))) end elseif (path.getextension(file) == ".rc") then _p('$(OBJDIR)/%s.res: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file)) _p('\t@echo $(notdir $<)') _p('\t$(SILENT) windres $< -O coff -o "$@" $(RESFLAGS)') elseif (path.getextension(file) == ".asm") then _p('$(OBJDIR)/%s.o: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file)) _p('\t@echo $(notdir $<)') local opts = '' if os.is('windows') then opts = '' elseif os.is('macosx') then opts = '-D OS_UNIX=1' else opts = '-D DONT_USE_UNDERLINE=1 -D OS_UNIX=1' end if not (prj.solution.nasmpath) then prj.solution.nasmpath = 'nasm' end _p('\t$(SILENT)'.._MAKE.esc(prj.solution.nasmpath)..' '..opts..' -i'.._MAKE.esc(path.getdirectory(file))..'/'..' -f '.. _MAKE.esc(prj.solution.nasmformat)..' -o $@ $<\n\t') _p('\t$(SILENT)'.._MAKE.esc(prj.solution.nasmpath)..' '..opts..' -i'.._MAKE.esc(path.getdirectory(file))..'/'.. ' -M -o $@ $< >$(OBJDIR)/$( 0 then _p('\t@echo Running pre-build commands') _p('\t%s', table.implode(cfg.prebuildcommands, "", "", "\n\t")) end _p(' endef') _p(' define PRELINKCMDS') if #cfg.prelinkcommands > 0 then _p('\t@echo Running pre-link commands') _p('\t%s', table.implode(cfg.prelinkcommands, "", "", "\n\t")) end _p(' endef') _p(' define POSTBUILDCMDS') if #cfg.postbuildcommands > 0 then _p('\t@echo Running post-build commands') _p('\t%s', table.implode(cfg.postbuildcommands, "", "", "\n\t")) end _p(' endef') _p('endif') _p('') end -- -- Precompiled header support -- function _.pchconfig(cfg) if not cfg.flags.NoPCH and cfg.pchheader then _p(' PCH = %s', _MAKE.esc(cfg.pchheader)) _p(' GCH = $(OBJDIR)/%s.gch', _MAKE.esc(path.getname(cfg.pchheader))) _p(' PCHINCLUDES = -I$(OBJDIR) -include $(OBJDIR)/%s', _MAKE.esc(path.getname(cfg.pchheader))) end end function _.pchrules(prj) _p('ifneq (,$(PCH))') _p('$(GCH): $(PCH) | $(OBJDIR)') _p('\t@echo $(notdir $<)') _p('\t-$(SILENT) cp $< $(OBJDIR)') if prj.language == "C" then _p('\t$(SILENT) $(CC) $(CFLAGS) -o "$@" -c "$<"') else _p('\t$(SILENT) $(CXX) $(CXXFLAGS) -x c++-header -o "$@" -c "$<"') end _p('endif') _p('') end