-- -- make_swift.lua -- Generate a Swift project makefile. -- local make = premake.make local swift = { } function premake.make_swift(prj) local tool = premake.gettool(prj) -- build a list of supported target platforms that also includes a generic build local platforms = premake.filterplatforms(prj.solution, tool.platforms, "Native") _p('# %s project makefile autogenerated by GENie', premake.action.current().shortname) _p('') _p('.SUFFIXES:') -- Delete the default suffix rules. _p('') -- set up the environment _p('ifndef config') _p(1, 'config=%s', _MAKE.esc(premake.getconfigname(prj.solution.configurations[1], platforms[1], true))) _p('endif') _p('') _p('ifndef verbose') _p(1, 'SILENT = @') _p('endif') _p('') -- identify the shell type _p('SHELLTYPE := msdos') _p('ifeq (,$(ComSpec)$(COMSPEC))') _p(1, 'SHELLTYPE := posix') _p('endif') _p('ifeq (/bin,$(findstring /bin,$(SHELL)))') _p(1, 'SHELLTYPE := posix') _p('endif') _p('ifeq (/bin,$(findstring /bin,$(MAKESHELL)))') _p(1, 'SHELLTYPE := posix') _p('endif') _p('') _p('ifeq (posix,$(SHELLTYPE))') _p(1, 'MKDIR = $(SILENT) mkdir -p "$(1)"') _p(1, 'COPY = $(SILENT) cp -fR "$(1)" "$(2)"') _p(1, 'RM = $(SILENT) rm -f "$(1)"') _p('else') _p(1, 'MKDIR = $(SILENT) mkdir "$(subst /,\\\\,$(1))" 2> nul || exit 0') _p(1, 'COPY = $(SILENT) copy /Y "$(subst /,\\\\,$(1))" "$(subst /,\\\\,$(2))"') _p(1, 'RM = $(SILENT) del /F "$(subst /,\\\\,$(1))" 2> nul || exit 0') _p('endif') _p('') _p('SWIFTC = %s', tool.swift) _p('SWIFTLINK = %s', tool.swiftc) _p('DSYMUTIL = %s', tool.dsymutil) _p('AR = %s', tool.ar) _p('') -- write configuration blocks for _, platform in ipairs(platforms) do for cfg in premake.eachconfig(prj, platform) do swift.generate_config(prj, cfg, tool) end end _p('.PHONY: ') _p('') _p('all: $(WORK_DIRS) $(TARGET)') _p('') _p('$(WORK_DIRS):') _p(1, '$(SILENT) $(call MKDIR,$@)') _p('') _p('SOURCES := \\') for _, file in ipairs(prj.files) do if path.isswiftfile(file) then _p(1, '%s \\', _MAKE.esc(file)) end end _p('') local objfiles = {} _p('OBJECTS_WITNESS := $(OBJDIR)/build.stamp') _p('OBJECTS := \\') for _, file in ipairs(prj.files) do if path.isswiftfile(file) then local objname = _MAKE.esc(swift.objectname(file)) table.insert(objfiles, objname) _p(1, '%s \\', objname) end end _p('') swift.file_rules(prj, objfiles) swift.linker(prj, tool) swift.generate_clean(prj) end function swift.objectname(file) return path.join("$(OBJDIR)", path.getname(file)..".o") end function swift.file_rules(prj, objfiles) -- use a witness file per recommendation for handling multiple outputs -- see https://www.gnu.org/software/automake/manual/html_node/Multiple-Outputs.html _p('$(OBJECTS_WITNESS): $(SOURCES)') _p(1, "@rm -f $(OBJDIR)/data.tmp") _p(1, "@touch $(OBJDIR)/data.tmp") _p(1, "$(SILENT) $(SWIFTC) -frontend -c $(SOURCES) -enable-objc-interop $(SDK) -I $(OUT_DIR) $(SWIFTC_FLAGS) -module-cache-path $(MODULECACHE_DIR) -D SWIFT_PACKAGE $(MODULE_MAPS) -emit-module-doc-path $(OUT_DIR)/$(MODULE_NAME).swiftdoc -module-name $(MODULE_NAME) -emit-module-path $(OUT_DIR)/$(MODULE_NAME).swiftmodule -num-threads 8 %s", table.arglist("-o", objfiles)) _p(1, "@mv -f $(OBJDIR)/data.tmp $(OBJECTS_WITNESS)") _p('') -- posix only for now _p('$(OBJECTS): $(OBJECTS_WITNESS)') _p(1, '@if test -f $@; then :; else \\') _p(2, 'rm -f $(OBJECTS_WITNESS); \\') _p(2, '$(MAKE) $(AM_MAKEFLAGS) $(OBJECTS_WITNESS); \\') _p(1, 'fi') _p('') end function swift.linker(prj, tool) local lddeps = make.list(premake.getlinks(prj, "siblings", "fullpath")) if prj.kind == "StaticLib" then _p("$(TARGET): $(OBJECTS) %s ", lddeps) _p(1, "$(SILENT) $(AR) cr $(AR_FLAGS) $@ $(OBJECTS) %s", (os.is("MacOSX") and " 2>&1 > /dev/null | sed -e '/.o) has no symbols$$/d'" or "")) else _p("$(TARGET): $(OBJECTS) $(LDDEPS)", lddeps) _p(1, "$(SILENT) $(SWIFTLINK) $(SDK) -L $(OUT_DIR) -o $@ $(SWIFTLINK_FLAGS) $(LD_FLAGS) $(OBJECTS)") _p("ifdef SYMBOLS") _p(1, "$(SILENT) $(DSYMUTIL) $(TARGET) -o $(SYMBOLS)") _p("endif") end _p('') end function swift.generate_clean(prj) _p('clean:') if (not prj.solution.messageskip) or (not table.contains(prj.solution.messageskip, "SkipCleaningMessage")) then _p('\t@echo Cleaning %s', prj.name) end _p('ifeq (posix,$(SHELLTYPE))') _p('\t$(SILENT) rm -f $(TARGET)') _p('\t$(SILENT) rm -rf $(OBJDIR)') _p('\t$(SILENT) rm -rf $(SYMBOLS)') _p('\t$(SILENT) rm -rf $(MODULECACHE_DIR)') _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('\t$(SILENT) if exist $(subst /,\\\\,$(SYMBOLS)) rmdir /s /q $(subst /,\\\\,$(SYMBOLS))') _p('\t$(SILENT) if exist $(subst /,\\\\,$(MODULECACHE_DIR)) rmdir /s /q $(subst /,\\\\,$(MODULECACHE_DIR))') _p('endif') _p('') end function swift.generate_config(prj, cfg, tool) _p('ifeq ($(config),%s)', _MAKE.esc(cfg.shortname)) _p(1, "OUT_DIR = %s", cfg.buildtarget.directory) _p(1, "MODULECACHE_DIR = $(OUT_DIR)/ModuleCache") _p(1, "TARGET = $(OUT_DIR)/%s", _MAKE.esc(cfg.buildtarget.name)) local objdir = path.join(cfg.objectsdir, prj.name .. ".build") _p(1, "OBJDIR = %s", objdir) _p(1, "MODULE_NAME = %s", prj.name) _p(1, "MODULE_MAPS = %s", make.list(tool.getmodulemaps(cfg))) _p(1, "SWIFTC_FLAGS = %s", make.list(tool.getswiftcflags(cfg))) _p(1, "SWIFTLINK_FLAGS = %s", make.list(tool.getswiftlinkflags(cfg))) _p(1, "AR_FLAGS = %s", make.list(tool.getarchiveflags(cfg, cfg, false))) _p(1, "LD_FLAGS = %s", make.list(tool.getldflags(cfg))) _p(1, "LDDEPS = %s", make.list(premake.getlinks(cfg, "siblings", "fullpath"))) if cfg.flags.Symbols then _p(1, "SYMBOLS = $(TARGET).dSYM") end local sdk = tool.get_sdk_path(cfg) if sdk then _p(1, "TOOLCHAIN_PATH = %s", tool.get_toolchain_path(cfg)) _p(1, "SDK_PATH = %s", sdk) _p(1, "PLATFORM_PATH = %s", tool.get_sdk_platform_path(cfg)) _p(1, "SDK = -sdk $(SDK_PATH)") else _p(1, "SDK_PATH =") _p(1, "SDK =") end _p(1,'WORK_DIRS = $(OUT_DIR) $(OBJDIR)') _p('endif') _p('') end