1-- -- 2-- make_cpp.lua 3-- Generate a C/C++ project makefile. 4-- Copyright (c) 2002-2013 Jason Perkins and the Premake project 5-- 6 7 premake.make.cpp = { } 8 premake.make.override = { } 9 premake.make.makefile_ignore = false 10 11 local cpp = premake.make.cpp 12 local make = premake.make 13 14 function premake.make_cpp(prj) 15 16 -- create a shortcut to the compiler interface 17 local cc = premake.gettool(prj) 18 19 -- build a list of supported target platforms that also includes a generic build 20 local platforms = premake.filterplatforms(prj.solution, cc.platforms, "Native") 21 22 -- output build configurations 23 local action = premake.action.current() 24 premake.gmake_cpp_header(prj, cc, platforms) 25 premake.gmake_cpp_configs(prj, cc, platforms) 26 table.sort(prj.allfiles) 27 28 -- list object directories 29 local objdirs = {} 30 local additionalobjdirs = {} 31 for _, file in ipairs(prj.allfiles) do 32 if path.issourcefile(file) then 33 objdirs[_MAKE.esc(path.getdirectory(path.trimdots(file)))] = 1 34 end 35 end 36 37 for _, custombuildtask in ipairs(prj.custombuildtask or {}) do 38 for _, buildtask in ipairs(custombuildtask or {}) do 39 additionalobjdirs[_MAKE.esc(path.getdirectory(path.getrelative(prj.location,buildtask[2])))] = 1 40 end 41 end 42 43 _p('OBJDIRS := \\') 44 _p('\t$(OBJDIR) \\') 45 for dir, _ in iter.sortByKeys(objdirs) do 46 _p('\t$(OBJDIR)/%s \\', dir) 47 end 48 for dir, _ in iter.sortByKeys(additionalobjdirs) do 49 _p('\t%s \\', dir) 50 end 51 _p('') 52 53 _p('RESOURCES := \\') 54 for _, file in ipairs(prj.allfiles) do 55 if path.isresourcefile(file) then 56 _p('\t$(OBJDIR)/%s.res \\', _MAKE.esc(path.getbasename(file))) 57 end 58 end 59 _p('') 60 61 -- main build rule(s) 62 _p('.PHONY: clean prebuild prelink') 63 _p('') 64 65 if os.is("MacOSX") and prj.kind == "WindowedApp" and not prj.options.SkipBundling then 66 _p('all: $(OBJDIRS) $(TARGETDIR) prebuild prelink $(TARGET) $(dir $(TARGETDIR))PkgInfo $(dir $(TARGETDIR))Info.plist') 67 else 68 _p('all: $(OBJDIRS) $(TARGETDIR) prebuild prelink $(TARGET)') 69 end 70 _p('\t@:') 71 _p('') 72 73 if (prj.kind == "StaticLib" and prj.options.ArchiveSplit) then 74 _p('define max_args') 75 _p('\t$(eval _args:=)') 76 _p('\t$(foreach obj,$3,$(eval _args+=$(obj))$(if $(word $2,$(_args)),$1 $(_args)$(EOL)$(eval _args:=)))') 77 _p('\t$(if $(_args),$1 $(_args))') 78 _p('endef') 79 _p('') 80 _p('define EOL') 81 _p('') 82 _p('') 83 _p('endef') 84 _p('') 85 end 86 87 -- target build rule 88 _p('$(TARGET): $(GCH) $(OBJECTS) $(LIBDEPS) $(EXTERNAL_LIBS) $(RESOURCES) $(OBJRESP) $(LDRESP) | $(TARGETDIR) $(OBJDIRS)') 89 90 if prj.kind == "StaticLib" then 91 if prj.msgarchiving then 92 _p('\t@echo ' .. prj.msgarchiving) 93 else 94 _p('\t@echo Archiving %s', prj.name) 95 end 96 if (not prj.archivesplit_size) then 97 prj.archivesplit_size=200 98 end 99 if (not prj.options.ArchiveSplit) then 100 _p('ifeq (posix,$(SHELLTYPE))') 101 _p('\t$(SILENT) rm -f $(TARGET)') 102 _p('else') 103 _p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGET)) del $(subst /,\\\\,$(TARGET))') 104 _p('endif') 105 _p('\t$(SILENT) $(LINKCMD) $(LINKOBJS)' .. (os.is("MacOSX") and " 2>&1 > /dev/null | sed -e '/.o) has no symbols$$/d'" or "")) 106 else 107 _p('\t$(call RM,$(TARGET))') 108 _p('\t@$(call max_args,$(LINKCMD),'.. prj.archivesplit_size ..',$(LINKOBJS))' .. (os.is("MacOSX") and " 2>&1 > /dev/null | sed -e '/.o) has no symbols$$/d'" or "")) 109 _p('\t$(SILENT) $(LINKCMD_NDX)') 110 end 111 else 112 if prj.msglinking then 113 _p('\t@echo ' .. prj.msglinking) 114 else 115 _p('\t@echo Linking %s', prj.name) 116 end 117 _p('\t$(SILENT) $(LINKCMD)') 118 end 119 120 _p('\t$(POSTBUILDCMDS)') 121 _p('') 122 123 -- Create destination directories. Can't use $@ for this because it loses the 124 -- escaping, causing issues with spaces and parenthesis 125 _p('$(TARGETDIR):') 126 premake.make_mkdirrule("$(TARGETDIR)") 127 128 _p('$(OBJDIRS):') 129 if (not prj.solution.messageskip) or (not table.contains(prj.solution.messageskip, "SkipCreatingMessage")) then 130 _p('\t@echo Creating $(@)') 131 end 132 _p('\t-$(call MKDIR,$@)') 133 _p('') 134 135 -- Mac OS X specific targets 136 if os.is("MacOSX") and prj.kind == "WindowedApp" and not prj.options.SkipBundling then 137 _p('$(dir $(TARGETDIR))PkgInfo:') 138 _p('$(dir $(TARGETDIR))Info.plist:') 139 _p('') 140 end 141 142 -- clean target 143 _p('clean:') 144 if (not prj.solution.messageskip) or (not table.contains(prj.solution.messageskip, "SkipCleaningMessage")) then 145 _p('\t@echo Cleaning %s', prj.name) 146 end 147 _p('ifeq (posix,$(SHELLTYPE))') 148 _p('\t$(SILENT) rm -f $(TARGET)') 149 _p('\t$(SILENT) rm -rf $(OBJDIR)') 150 _p('else') 151 _p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGET)) del $(subst /,\\\\,$(TARGET))') 152 _p('\t$(SILENT) if exist $(subst /,\\\\,$(OBJDIR)) rmdir /s /q $(subst /,\\\\,$(OBJDIR))') 153 _p('endif') 154 _p('') 155 156 -- custom build step targets 157 _p('prebuild:') 158 _p('\t$(PREBUILDCMDS)') 159 _p('') 160 161 _p('prelink:') 162 _p('\t$(PRELINKCMDS)') 163 _p('') 164 165 -- precompiler header rule 166 cpp.pchrules(prj) 167 168 -- per-file build rules 169 cpp.fileRules(prj, cc) 170 171 -- per-dependency build rules 172 cpp.dependencyRules(prj) 173 174 for _, custombuildtask in ipairs(prj.custombuildtask or {}) do 175 for _, buildtask in ipairs(custombuildtask or {}) do 176 local deps = string.format("%s ",path.getrelative(prj.location,buildtask[1])) 177 for _, depdata in ipairs(buildtask[3] or {}) do 178 deps = deps .. string.format("%s ",path.getrelative(prj.location,depdata)) 179 end 180 _p('%s: %s | $(TARGETDIR) $(OBJDIRS)' 181 ,path.getrelative(prj.location,buildtask[2]) 182 , deps 183 ) 184 for _, cmdline in ipairs(buildtask[4] or {}) do 185 local cmd = cmdline 186 local num = 1 187 for _, depdata in ipairs(buildtask[3] or {}) do 188 cmd = string.gsub(cmd,"%$%(" .. num .."%)", string.format("%s ",path.getrelative(prj.location,depdata))) 189 num = num + 1 190 end 191 cmd = string.gsub(cmd, "%$%(<%)", "$<") 192 cmd = string.gsub(cmd, "%$%(@%)", "$@") 193 194 _p('\t$(SILENT) %s',cmd) 195 196 end 197 _p('') 198 end 199 end 200 201 -- include the dependencies, built by GCC (with the -MMD flag) 202 _p('-include $(OBJECTS:%%.o=%%.d)') 203 _p('ifneq (,$(PCH))') 204 _p(' -include $(OBJDIR)/$(notdir $(PCH)).d') 205 _p(' -include $(OBJDIR)/$(notdir $(PCH))_objc.d') 206 _p('endif') 207 end 208 209 210 211-- 212-- Write the makefile header 213-- 214 215 function premake.gmake_cpp_header(prj, cc, platforms) 216 _p('# %s project makefile autogenerated by GENie', premake.action.current().shortname) 217 218 -- set up the environment 219 _p('ifndef config') 220 _p(' config=%s', _MAKE.esc(premake.getconfigname(prj.solution.configurations[1], platforms[1], true))) 221 _p('endif') 222 _p('') 223 224 _p('ifndef verbose') 225 _p(' SILENT = @') 226 _p('endif') 227 _p('') 228 229 -- identify the shell type 230 _p('SHELLTYPE := msdos') 231 _p('ifeq (,$(ComSpec)$(COMSPEC))') 232 _p(' SHELLTYPE := posix') 233 _p('endif') 234 _p('ifeq (/bin,$(findstring /bin,$(SHELL)))') 235 _p(' SHELLTYPE := posix') 236 _p('endif') 237 _p('ifeq (/bin,$(findstring /bin,$(MAKESHELL)))') 238 _p(' SHELLTYPE := posix') 239 _p('endif') 240 _p('') 241 242 _p('ifeq (posix,$(SHELLTYPE))') 243 _p(' MKDIR = $(SILENT) mkdir -p "$(1)"') 244 _p(' COPY = $(SILENT) cp -fR "$(1)" "$(2)"') 245 _p(' RM = $(SILENT) rm -f "$(1)"') 246 _p('else') 247 _p(' MKDIR = $(SILENT) mkdir "$(subst /,\\\\,$(1))" 2> nul || exit 0') 248 _p(' COPY = $(SILENT) copy /Y "$(subst /,\\\\,$(1))" "$(subst /,\\\\,$(2))"') 249 _p(' RM = $(SILENT) del /F "$(subst /,\\\\,$(1))" 2> nul || exit 0') 250 _p('endif') 251 _p('') 252 253 _p('CC = %s', cc.cc) 254 _p('CXX = %s', cc.cxx) 255 _p('AR = %s', cc.ar) 256 _p('') 257 258 _p('ifndef RESCOMP') 259 _p(' ifdef WINDRES') 260 _p(' RESCOMP = $(WINDRES)') 261 _p(' else') 262 _p(' RESCOMP = %s', cc.rc or 'windres') 263 _p(' endif') 264 _p('endif') 265 _p('') 266 267 if (not premake.make.makefile_ignore) then 268 _p('MAKEFILE = %s', _MAKE.getmakefilename(prj, true)) 269 _p('') 270 end 271 end 272 273-- 274-- Write a block of configuration settings. 275-- 276 277 local function is_excluded(prj, cfg, file) 278 if table.icontains(prj.excludes, file) then 279 return true 280 end 281 282 if table.icontains(cfg.excludes, file) then 283 return true 284 end 285 286 return false 287 end 288 289 function premake.gmake_cpp_configs(prj, cc, platforms) 290 for _, platform in ipairs(platforms) do 291 for cfg in premake.eachconfig(prj, platform) do 292 premake.gmake_cpp_config(prj, cfg, cc) 293 end 294 end 295 end 296 297 function premake.gmake_cpp_config(prj, cfg, cc) 298 _p('ifeq ($(config),%s)', _MAKE.esc(cfg.shortname)) 299 300 -- if this platform requires a special compiler or linker, list it here 301 cpp.platformtools(cfg, cc) 302 303 local targetDir = _MAKE.esc(cfg.buildtarget.directory) 304 305 _p(' ' .. (table.contains(premake.make.override,"OBJDIR") and "override " or "") .. 'OBJDIR = %s', _MAKE.esc(cfg.objectsdir)) 306 _p(' ' .. (table.contains(premake.make.override,"TARGETDIR") and "override " or "") .. 'TARGETDIR = %s', iif(targetDir == "", ".", targetDir)) 307 _p(' ' .. (table.contains(premake.make.override,"TARGET") and "override " or "") .. 'TARGET = $(TARGETDIR)/%s', _MAKE.esc(cfg.buildtarget.name)) 308 _p(' DEFINES +=%s', make.list(_MAKE.escquote(cc.getdefines(cfg.defines)))) 309 310 local id = make.list(cc.getincludedirs(cfg.includedirs)); 311 local uid = make.list(cc.getquoteincludedirs(cfg.userincludedirs)) 312 local sid = make.list(cc.getsystemincludedirs(cfg.systemincludedirs)) 313 314 if id ~= "" then 315 _p(' INCLUDES +=%s', id) 316 end 317 318 if uid ~= "" then 319 _p(' INCLUDES +=%s', uid) 320 end 321 322 if sid ~= "" then 323 _p(' INCLUDES +=%s', sid) 324 end 325 326 -- set up precompiled headers 327 cpp.pchconfig(cfg) 328 329 -- CPPFLAGS, CFLAGS, CXXFLAGS, and RESFLAGS 330 cpp.flags(cfg, cc) 331 332 -- write out libraries, linker flags, and the link command 333 cpp.linker(prj, cfg, cc) 334 335 table.sort(cfg.files) 336 337 -- add objects for compilation, and remove any that are excluded per config. 338 if cfg.flags.UseObjectResponseFile then 339 _p(' OBJRESP = $(OBJDIR)/%s_objects', prj.name) 340 else 341 _p(' OBJRESP =') 342 end 343 _p(' OBJECTS := \\') 344 for _, file in ipairs(cfg.files) do 345 if path.issourcefile(file) then 346 -- check if file is excluded. 347 if not is_excluded(prj, cfg, file) then 348 -- if not excluded, add it. 349 _p('\t$(OBJDIR)/%s.o \\' 350 , _MAKE.esc(path.trimdots(path.removeext(file))) 351 ) 352 end 353 end 354 end 355 _p('') 356 357 _p(' define PREBUILDCMDS') 358 if #cfg.prebuildcommands > 0 then 359 _p('\t@echo Running pre-build commands') 360 _p('\t%s', table.implode(cfg.prebuildcommands, "", "", "\n\t")) 361 end 362 _p(' endef') 363 364 _p(' define PRELINKCMDS') 365 if #cfg.prelinkcommands > 0 then 366 _p('\t@echo Running pre-link commands') 367 _p('\t%s', table.implode(cfg.prelinkcommands, "", "", "\n\t")) 368 end 369 _p(' endef') 370 371 _p(' define POSTBUILDCMDS') 372 if #cfg.postbuildcommands > 0 then 373 _p('\t@echo Running post-build commands') 374 _p('\t%s', table.implode(cfg.postbuildcommands, "", "", "\n\t")) 375 end 376 _p(' endef') 377 378 -- write out config-level makesettings blocks 379 make.settings(cfg, cc) 380 381 _p('endif') 382 _p('') 383 end 384 385 386-- 387-- Platform support 388-- 389 390 function cpp.platformtools(cfg, cc) 391 local platform = cc.platforms[cfg.platform] 392 if platform.cc then 393 _p(' CC = %s', platform.cc) 394 end 395 if platform.cxx then 396 _p(' CXX = %s', platform.cxx) 397 end 398 if platform.ar then 399 _p(' AR = %s', platform.ar) 400 end 401 end 402 403 404-- 405-- Configurations 406-- 407 408 function cpp.flags(cfg, cc) 409 410 if cfg.pchheader and not cfg.flags.NoPCH then 411 _p(' FORCE_INCLUDE += -include $(OBJDIR)/$(notdir $(PCH))') 412 _p(' FORCE_INCLUDE_OBJC += -include $(OBJDIR)/$(notdir $(PCH))_objc') 413 end 414 415 if #cfg.forcedincludes > 0 then 416 _p(' FORCE_INCLUDE += -include %s' 417 ,_MAKE.esc(table.concat(cfg.forcedincludes, ";"))) 418 end 419 420 _p(' ALL_CPPFLAGS += $(CPPFLAGS) %s $(DEFINES) $(INCLUDES)', table.concat(cc.getcppflags(cfg), " ")) 421 422 _p(' ALL_ASMFLAGS += $(ASMFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cfg.buildoptions, cfg.buildoptions_asm))) 423 _p(' ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cfg.buildoptions, cfg.buildoptions_c))) 424 _p(' ALL_CXXFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cc.getcxxflags(cfg), cfg.buildoptions, cfg.buildoptions_cpp))) 425 _p(' ALL_OBJCFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cc.getobjcflags(cfg), cfg.buildoptions, cfg.buildoptions_objc))) 426 _p(' ALL_OBJCPPFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cc.getcxxflags(cfg), cc.getobjcflags(cfg), cfg.buildoptions, cfg.buildoptions_objcpp))) 427 428 _p(' ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)%s', 429 make.list(table.join(cc.getdefines(cfg.resdefines), 430 cc.getincludedirs(cfg.resincludedirs), cfg.resoptions))) 431 end 432 433 434-- 435-- Linker settings, including the libraries to link, the linker flags, 436-- and the linker command. 437-- 438 439 function cpp.linker(prj, cfg, cc) 440 local libdeps 441 local lddeps 442 443 if #cfg.wholearchive > 0 then 444 libdeps = {} 445 lddeps = {} 446 447 for _, linkcfg in ipairs(premake.getlinks(cfg, "siblings", "object")) do 448 local linkpath = path.rebase(linkcfg.linktarget.fullpath, linkcfg.location, cfg.location) 449 450 if table.icontains(cfg.wholearchive, linkcfg.project.name) then 451 lddeps = table.join(lddeps, cc.wholearchive(linkpath)) 452 else 453 table.insert(lddeps, linkpath) 454 end 455 456 table.insert(libdeps, linkpath) 457 end 458 459 libdeps = make.list(_MAKE.esc(libdeps)) 460 lddeps = make.list(_MAKE.esc(lddeps)) 461 else 462 libdeps = make.list(_MAKE.esc(premake.getlinks(cfg, "siblings", "fullpath"))) 463 lddeps = libdeps 464 end 465 466 _p(' ALL_LDFLAGS += $(LDFLAGS)%s', make.list(table.join(cc.getlibdirflags(cfg), cc.getldflags(cfg), cfg.linkoptions))) 467 _p(' LIBDEPS +=%s', libdeps) 468 _p(' LDDEPS +=%s', lddeps) 469 470 if cfg.flags.UseLDResponseFile then 471 _p(' LDRESP = $(OBJDIR)/%s_libs', prj.name) 472 _p(' LIBS += @$(LDRESP)%s', make.list(cc.getlinkflags(cfg))) 473 else 474 _p(' LDRESP =') 475 _p(' LIBS += $(LDDEPS)%s', make.list(cc.getlinkflags(cfg))) 476 end 477 478 _p(' EXTERNAL_LIBS +=%s', make.list(cc.getlibfiles(cfg))) 479 _p(' LINKOBJS = %s', (cfg.flags.UseObjectResponseFile and "@$(OBJRESP)" or "$(OBJECTS)")) 480 481 if cfg.kind == "StaticLib" then 482 if (not prj.options.ArchiveSplit) then 483 _p(' LINKCMD = $(AR) %s $(TARGET)', make.list(cc.getarchiveflags(prj, cfg, false))) 484 else 485 _p(' LINKCMD = $(AR) %s $(TARGET)', make.list(cc.getarchiveflags(prj, cfg, false))) 486 _p(' LINKCMD_NDX = $(AR) %s $(TARGET)', make.list(cc.getarchiveflags(prj, cfg, true))) 487 end 488 else 489 local tool = iif(cfg.language == "C", "CC", "CXX") 490 local startgroup = '' 491 local endgroup = '' 492 if (cfg.flags.LinkSupportCircularDependencies) then 493 startgroup = '-Wl,--start-group ' 494 endgroup = ' -Wl,--end-group' 495 end 496 _p(' LINKCMD = $(%s) -o $(TARGET) $(LINKOBJS) $(RESOURCES) $(ARCH) $(ALL_LDFLAGS) %s$(LIBS)%s', tool, startgroup, endgroup) 497 end 498 end 499 500 501-- 502-- Precompiled header support 503-- 504 505 function cpp.pchconfig(cfg) 506 507 -- If there is no header, or if PCH has been disabled, I can early out 508 509 if not cfg.pchheader or cfg.flags.NoPCH then 510 return 511 end 512 513 -- Visual Studio requires the PCH header to be specified in the same way 514 -- it appears in the #include statements used in the source code; the PCH 515 -- source actual handles the compilation of the header. GCC compiles the 516 -- header file directly, and needs the file's actual file system path in 517 -- order to locate it. 518 519 -- To maximize the compatibility between the two approaches, see if I can 520 -- locate the specified PCH header on one of the include file search paths 521 -- and, if so, adjust the path automatically so the user doesn't have 522 -- add a conditional configuration to the project script. 523 524 local pch = cfg.pchheader 525 for _, incdir in ipairs(cfg.includedirs) do 526 527 -- convert this back to an absolute path for os.isfile() 528 local abspath = path.getabsolute(path.join(cfg.project.location, incdir)) 529 530 local testname = path.join(abspath, pch) 531 if os.isfile(testname) then 532 pch = path.getrelative(cfg.location, testname) 533 break 534 end 535 end 536 537 _p(' PCH = %s', _MAKE.esc(pch)) 538 _p(' GCH = $(OBJDIR)/$(notdir $(PCH)).gch') 539 _p(' GCH_OBJC = $(OBJDIR)/$(notdir $(PCH))_objc.gch') 540 541 end 542 543 544 function cpp.pchrules(prj) 545 _p('ifneq (,$(PCH))') 546 _p('$(GCH): $(PCH) $(MAKEFILE) | $(OBJDIR)') 547 if prj.msgprecompile then 548 _p('\t@echo ' .. prj.msgprecompile) 549 else 550 _p('\t@echo $(notdir $<)') 551 end 552 553 local cmd = iif(prj.language == "C", "$(CC) $(ALL_CFLAGS) -x c-header", "$(CXX) $(ALL_CXXFLAGS) -x c++-header") 554 _p('\t$(SILENT) %s $(DEFINES) $(INCLUDES) -o "$@" -c "$<"', cmd) 555 556 _p('') 557 558 _p('$(GCH_OBJC): $(PCH) $(MAKEFILE) | $(OBJDIR)') 559 if prj.msgprecompile then 560 _p('\t@echo ' .. prj.msgprecompile) 561 else 562 _p('\t@echo $(notdir $<)') 563 end 564 565 local cmd = iif(prj.language == "C", "$(CC) $(ALL_OBJCFLAGS) -x objective-c-header", "$(CXX) $(ALL_OBJCPPFLAGS) -x objective-c++-header") 566 _p('\t$(SILENT) %s $(DEFINES) $(INCLUDES) -o "$@" -c "$<"', cmd) 567 568 _p('endif') 569 _p('') 570 end 571 572 573-- 574-- Build command for a single file. 575-- 576 577 function cpp.fileRules(prj, cc) 578 local platforms = premake.filterplatforms(prj.solution, cc.platforms, "Native") 579 580 _p('ifneq (,$(OBJRESP))') 581 _p('$(OBJRESP): $(OBJECTS) | $(TARGETDIR) $(OBJDIRS)') 582 _p('\t$(SILENT) echo $^') 583 _p('\t$(SILENT) echo $^ > $@') 584 _p('endif') 585 _p('') 586 587 _p('ifneq (,$(LDRESP))') 588 _p('$(LDRESP): $(LDDEPS) | $(TARGETDIR) $(OBJDIRS)') 589 _p('\t$(SILENT) echo $^') 590 _p('\t$(SILENT) echo $^ > $@') 591 _p('endif') 592 _p('') 593 594 table.sort(prj.allfiles) 595 for _, file in ipairs(prj.allfiles or {}) do 596 if path.issourcefile(file) then 597 if (path.isobjcfile(file)) then 598 _p('$(OBJDIR)/%s.o: %s $(GCH_OBJC) $(MAKEFILE) | $(OBJDIR)/%s' 599 , _MAKE.esc(path.trimdots(path.removeext(file))) 600 , _MAKE.esc(file) 601 , _MAKE.esc(path.getdirectory(path.trimdots(file))) 602 ) 603 else 604 _p('$(OBJDIR)/%s.o: %s $(GCH) $(MAKEFILE) | $(OBJDIR)/%s' 605 , _MAKE.esc(path.trimdots(path.removeext(file))) 606 , _MAKE.esc(file) 607 , _MAKE.esc(path.getdirectory(path.trimdots(file))) 608 ) 609 end 610 if (path.isobjcfile(file) and prj.msgcompile_objc) then 611 _p('\t@echo ' .. prj.msgcompile_objc) 612 elseif prj.msgcompile then 613 _p('\t@echo ' .. prj.msgcompile) 614 else 615 _p('\t@echo $(notdir $<)') 616 end 617 if (path.isobjcfile(file)) then 618 if (path.iscfile(file)) then 619 _p('\t$(SILENT) $(CXX) $(ALL_OBJCFLAGS) $(FORCE_INCLUDE_OBJC) -o "$@" -c "$<"') 620 else 621 _p('\t$(SILENT) $(CXX) $(ALL_OBJCPPFLAGS) $(FORCE_INCLUDE_OBJC) -o "$@" -c "$<"') 622 end 623 elseif (path.isasmfile(file)) then 624 _p('\t$(SILENT) $(CC) $(ALL_ASMFLAGS) -o "$@" -c "$<"') 625 else 626 cpp.buildcommand(path.iscfile(file) and not prj.options.ForceCPP, "o") 627 end 628 for _, task in ipairs(prj.postcompiletasks or {}) do 629 _p('\t$(SILENT) %s', task) 630 _p('') 631 end 632 633 _p('') 634 elseif (path.getextension(file) == ".rc") then 635 _p('$(OBJDIR)/%s.res: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file)) 636 if prj.msgresource then 637 _p('\t@echo ' .. prj.msgresource) 638 else 639 _p('\t@echo $(notdir $<)') 640 end 641 _p('\t$(SILENT) $(RESCOMP) $< -O coff -o "$@" $(ALL_RESFLAGS)') 642 _p('') 643 end 644 end 645 end 646 647 function cpp.dependencyRules(prj) 648 for _, dependency in ipairs(prj.dependency or {}) do 649 for _, dep in ipairs(dependency or {}) do 650 if (dep[3]==nil or dep[3]==false) then 651 _p('$(OBJDIR)/%s.o: %s' 652 , _MAKE.esc(path.trimdots(path.removeext(path.getrelative(prj.location, dep[1])))) 653 , _MAKE.esc(path.getrelative(prj.location, dep[2])) 654 ) 655 else 656 _p('%s: %s' 657 , _MAKE.esc(dep[1]) 658 , _MAKE.esc(path.getrelative(prj.location, dep[2])) 659 ) 660 end 661 _p('') 662 end 663 end 664 end 665 666 667 function cpp.buildcommand(iscfile, objext) 668 local flags = iif(iscfile, '$(CC) $(ALL_CFLAGS)', '$(CXX) $(ALL_CXXFLAGS)') 669 _p('\t$(SILENT) %s $(FORCE_INCLUDE) -o "$@" -c "$<"', flags, objext) 670 end 671