From b0ab905e2ae98b4ebb66eea9e0a635fc834019be Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 13 Feb 2019 22:37:00 +0800 Subject: add cmakelists plugin stub --- xmake/plugins/project/cmake/cmakelists.lua | 53 +++ xmake/plugins/project/main.lua | 4 +- xmake/plugins/project/make/makefile.lua | 532 ++++++++++++++++++++++++++++ xmake/plugins/project/makefile/makefile.lua | 532 ---------------------------- 4 files changed, 588 insertions(+), 533 deletions(-) create mode 100644 xmake/plugins/project/cmake/cmakelists.lua create mode 100644 xmake/plugins/project/make/makefile.lua delete mode 100644 xmake/plugins/project/makefile/makefile.lua diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua new file mode 100644 index 000000000..62bcae12b --- /dev/null +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -0,0 +1,53 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2019, TBOOX Open Source Group. +-- +-- @author ruki +-- @file cmakelists.lua +-- + +-- imports +import("core.tool.compiler") +import("core.project.project") +import("core.language.language") +import("core.platform.platform") + +-- make all +function _make_all(cmakelists) + +end + +-- make +function make(outputdir) + + -- enter project directory + local oldir = os.cd(os.projectdir()) + + -- open the cmakelists + local cmakelists = io.open(path.join(outputdir, "CMakeLists.txt"), "w") + + -- make all + _make_all(cmakelists) + + -- close the cmakelists + cmakelists:close() + + -- leave project directory + os.cd(oldir) +end diff --git a/xmake/plugins/project/main.lua b/xmake/plugins/project/main.lua index 787dafe92..75da9309f 100644 --- a/xmake/plugins/project/main.lua +++ b/xmake/plugins/project/main.lua @@ -26,7 +26,8 @@ import("core.base.option") import("core.base.task") import("core.platform.environment") -import("makefile.makefile") +import("make.makefile") +import("cmake.cmakelists") import("vstudio.vs2002") import("vstudio.vs2003") import("vstudio.vs2005") @@ -45,6 +46,7 @@ function _make(kind) local maps = { makefile = makefile.make + , cmakelists = cmakelists.make , vs2002 = vs2002.make , vs2003 = vs2003.make , vs2005 = vs2005.make diff --git a/xmake/plugins/project/make/makefile.lua b/xmake/plugins/project/make/makefile.lua new file mode 100644 index 000000000..9e2f2a51d --- /dev/null +++ b/xmake/plugins/project/make/makefile.lua @@ -0,0 +1,532 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2019, TBOOX Open Source Group. +-- +-- @author ruki +-- @file makefile.lua +-- + +-- imports +import("core.tool.compiler") +import("core.project.project") +import("core.language.language") +import("core.platform.platform") + +-- get log makefile +function _logfile() + + -- get it + return vformat("$(buildir)/.build.log") +end + +-- mkdir directory +function _mkdir(makefile, dir) + + if is_plat("windows") then + makefile:print("\t-@mkdir %s > NUL 2>&1", dir) + else + makefile:print("\t@mkdir -p %s", dir) + end +end + +-- copy file +function _cp(makefile, sourcefile, targetfile) + + -- copy file + if is_plat("windows") then + makefile:print("\t@copy /Y %s %s > NUL 2>&1", sourcefile, targetfile) + else + makefile:print("\t@cp %s %s", sourcefile, targetfile) + end +end + +-- try to remove the given file or directory +function _tryrm(makefile, filedir) + + -- remove it + if is_plat("windows") then + if os.isdir(filedir) then + makefile:print("\t@rmdir /S /Q %s > NUL 2>&1", filedir) + elseif os.isfile(filedir) then + makefile:print("\t@del /F /Q %s > NUL 2>&1", filedir) + end + else + if os.isdir(filedir) then + makefile:print("\t@rm -rf %s", filedir) + elseif os.isfile(filedir) then + makefile:print("\t@rm -f %s", filedir) + end + end +end + +-- remove the given files or directories +function _remove(makefile, filedirs) + for _, filedir in ipairs(filedirs) do + _tryrm(makefile, filedir) + end +end + +-- make common flags +function _make_common_flags(target, sourcekind, sourcebatch) + + -- make source flags + local sourceflags = {} + local flags_stats = {} + local files_count = 0 + local first_flags = nil + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + + -- make compiler flags + local flags = compiler.compflags(sourcefile, {target = target, sourcekind = sourcekind}) + for _, flag in ipairs(flags) do + flags_stats[flag] = (flags_stats[flag] or 0) + 1 + end + + -- update files count + files_count = files_count + 1 + + -- save first flags + if first_flags == nil then + first_flags = flags + end + + -- save source flags + sourceflags[sourcefile] = flags + end + + -- make common flags + local commonflags = {} + for _, flag in ipairs(first_flags) do + if flags_stats[flag] == files_count then + table.insert(commonflags, flag) + end + end + + -- remove common flags from source flags + local sourceflags_ = {} + for sourcefile, flags in pairs(sourceflags) do + local otherflags = {} + for _, flag in ipairs(flags) do + if flags_stats[flag] ~= files_count then + table.insert(otherflags, flag) + end + end + sourceflags_[sourcefile] = otherflags + end + + -- ok? + return commonflags, sourceflags_ +end + +-- make the object for the *.[o|obj] source file +function _make_object_for_object(makefile, target, sourcefile, objectfile) + + -- make command + local cmd = format("xmake l cp %s %s", sourcefile, objectfile) + + -- make head + makefile:printf("%s:", objectfile) + + -- make dependence + makefile:print(" %s", sourcefile) + + -- make body + makefile:print("\t@echo inserting.$(mode) %s", sourcefile) + makefile:print("\t@%s", cmd) + + -- make tail + makefile:print("") + +end + +-- make the object for the *.[a|lib] source file +function _make_object_for_static(makefile, target, sourcefile, objectfile) + + -- not supported + raise("source file: %s not supported!", sourcefile) +end + +-- make the object +function _make_object(makefile, target, sourcefile, objectfile, sourceflags) + + -- get the source file kind + local sourcekind = language.sourcekind_of(sourcefile) + + -- make the object for the *.o/obj source makefile + if sourcekind == "obj" then + return _make_object_for_object(makefile, target, sourcefile, objectfile) + -- make the object for the *.[a|lib] source file + elseif sourcekind == "lib" then + return _make_object_for_static(makefile, target, sourcefile, objectfile) + end + + -- get program + local program = platform.tool(sourcekind) + + -- get complier flags + local compflags = sourceflags[sourcefile] + + -- make command + local macro = "$(" .. target:name() .. '_' .. sourcekind:upper() .. ")" + local command = compiler.compcmd(sourcefile, objectfile, {compflags = table.join(macro, compflags)}) + + -- replace program to $(XX) + local p, e = command:find("\"" .. program .. "\"", 1, true) + if not p then + p, e = command:find(program, 1, true) + end + if p then + command = format("%s$(%s)%s", command:sub(1, p - 1), sourcekind:upper(), command:sub(e + 1)) + end + + -- replace ccache to $(CCACHE) + local ccache = false + p, e = command:find("ccache", 1, true) + if p then + command = format("%s$(%s)%s", command:sub(1, p - 1), "CCACHE", command:sub(e + 1)) + ccache = true + end + + -- make head + makefile:printf("%s:", objectfile) + + -- make dependence + makefile:print(" %s", sourcefile) + + -- make body + makefile:print("\t@echo %scompiling.$(mode) %s", ifelse(ccache, "ccache ", ""), sourcefile) + _mkdir(makefile, path.directory(objectfile)) + makefile:writef("\t@%s > %s 2>&1\n", command, _logfile()) + + -- make tail + makefile:print("") +end + +-- make each objects +function _make_each_objects(makefile, target, sourcekind, sourcebatch, sourceflags) + + -- make them + for index, objectfile in ipairs(sourcebatch.objectfiles) do + _make_object(makefile, target, sourcebatch.sourcefiles[index], objectfile, sourceflags) + end +end + +-- make single object +function _make_single_object(makefile, target, sourcekind, sourcebatch, sourceflags) + + -- get source and object files + local sourcefiles = sourcebatch.sourcefiles + local objectfiles = sourcebatch.objectfiles + local dependfiles = sourcebatch.dependfiles + + -- get program + local program = platform.tool(sourcekind) + + -- make command + local macro = "$(" .. target:name() .. '_' .. sourcekind:upper() .. ")" + local command = compiler.compcmd(sourcefiles, objectfiles, {compflags = macro}) + + -- replace program to $(XX) + local p, e = command:find(program, 1, true) + if p then + command = format("%s$(%s)%s", command:sub(1, p - 1), sourcekind:upper(), command:sub(e + 1)) + end + + -- replace ccache to $(CCACHE) + local ccache = false + p, e = command:find("ccache", 1, true) + if p then + command = format("%s$(%s)%s", command:sub(1, p - 1), "CCACHE", command:sub(e + 1)) + ccache = true + end + + -- make head + makefile:printf("%s:", objectfiles) + + -- make dependence + for _, sourcefile in ipairs(sourcefiles) do + makefile:printf(" %s", sourcefile) + end + makefile:print("") + + -- make body + for _, sourcefile in ipairs(sourcefiles) do + makefile:print("\t@echo %scompiling.$(mode) %s", ifelse(ccache, "ccache ", ""), sourcefile) + end + _mkdir(makefile, path.directory(objectfiles)) + makefile:writef("\t@%s > %s 2>&1\n", command, _logfile()) + + -- make tail + makefile:print("") +end + +-- make phony +function _make_phony(makefile, target) + + -- make dependence for the dependent targets + makefile:printf("%s:", target:name()) + for _, dep in ipairs(target:get("deps")) do + makefile:write(" " .. dep) + end + makefile:print("") +end + +-- make target +function _make_target(makefile, target, targetflags) + + -- is phony target? + if target:isphony() then + return _make_phony(makefile, target) + end + + -- make head + local targetfile = target:targetfile() + makefile:print("%s: %s", target:name(), targetfile) + makefile:printf("%s:", targetfile) + + -- make dependence for the dependent targets + for _, dep in ipairs(target:get("deps")) do + makefile:write(" " .. project.target(dep):targetfile()) + end + + -- make dependence for objects + local objectfiles = target:objectfiles() + for _, objectfile in ipairs(objectfiles) do + makefile:write(" " .. objectfile) + end + + -- make dependence end + makefile:print("") + + -- get linker kind + local linkerkind = target:linker():kind() + + -- get program + local program = platform.tool(linkerkind) + + -- get command + local command = target:linkcmd() + + -- replace linkflags to $(XX) + local p, e = command:find(os.args(target:linkflags()), 1, true) + if p then + command = format("%s$(%s_%s)%s", command:sub(1, p - 1), target:name(), (linkerkind:upper():gsub('%-', '_')), command:sub(e + 1)) + end + + -- replace program to $(XX) + p, e = command:find("\"" .. program .. "\"", 1, true) + if not p then + p, e = command:find(program, 1, true) + end + if p then + command = format("%s$(%s)%s", command:sub(1, p - 1), (linkerkind:upper():gsub('%-', '_')), command:sub(e + 1)) + end + + -- make body + makefile:print("\t@echo linking.$(mode) %s", path.filename(targetfile)) + _mkdir(makefile, path.directory(targetfile)) + makefile:writef("\t@%s > %s 2>&1\n", command, _logfile()) + + -- TODO make header directories (deprecated) + local dstheaderdirs = {} + local srcheaders, dstheaders = target:headerfiles() + for _, dstheader in ipairs(dstheaders) do + dstheaderdirs[path.directory(dstheader)] = true + end + for dstheaderdir, _ in pairs(dstheaderdirs) do + _mkdir(makefile, dstheaderdir) + end + + -- copy headers + if srcheaders and dstheaders then + local i = 1 + for _, srcheader in ipairs(srcheaders) do + local dstheader = dstheaders[i] + if dstheader then + _cp(makefile, srcheader, dstheader) + end + i = i + 1 + end + end + + -- make tail + makefile:print("") + + -- build source batches + for sourcekind, sourcebatch in pairs(target:sourcebatches()) do + if not sourcebatch.rulename then + -- compile source files to single object at once + local sourceflags = targetflags[target:name() .. '_' .. sourcekind:upper()] + if type(sourcebatch.objectfiles) == "string" then + _make_single_object(makefile, target, sourcekind, sourcebatch, sourceflags) + else + _make_each_objects(makefile, target, sourcekind, sourcebatch, sourceflags) + end + end + end +end + +-- make all +function _make_all(makefile) + + -- make variables for ccache + makefile:print("CCACHE=ccache") + + -- make variables for source kinds + for sourcekind, _ in pairs(language.sourcekinds()) do + local program = platform.tool(sourcekind) + if program and program ~= "" then + makefile:print("%s=%s", sourcekind:upper(), program) + end + end + makefile:print("") + + -- make variables for linker kinds + local linkerkinds = {} + for _, _linkerkinds in pairs(language.targetkinds()) do + table.join2(linkerkinds, _linkerkinds) + end + for _, linkerkind in ipairs(table.unique(linkerkinds)) do + local program = platform.tool(linkerkind) + if program and program ~= "" then + makefile:print("%s=%s", (linkerkind:upper():gsub('%-', '_')), program) + end + end + makefile:print("") + + -- TODO + -- disable precompiled header first + for _, target in pairs(project.targets()) do + target:set("pcheader", nil) + target:set("pcxxheader", nil) + end + + -- make variables for target flags + local targetflags = {} + for targetname, target in pairs(project.targets()) do + if not target:isphony() then + for sourcekind, sourcebatch in pairs(target:sourcebatches()) do + if not sourcebatch.rulename then + local commonflags, sourceflags = _make_common_flags(target, sourcekind, sourcebatch) + makefile:print("%s_%s=%s", targetname, sourcekind:upper(), os.args(commonflags)) + targetflags[targetname .. '_' .. sourcekind:upper()] = sourceflags + end + end + makefile:print("%s_%s=%s", targetname, target:linker():kind():upper(), os.args(target:linkflags())) + end + end + makefile:print("") + + -- make all + local default = "" + for targetname, target in pairs(project.targets()) do + local isdefault = target:get("default") + if isdefault == nil or isdefault == true then + default = default .. " " .. targetname + end + end + makefile:print("default: %s\n", default) + local all = "" + for targetname, _ in pairs(project.targets()) do + all = all .. " " .. targetname + end + makefile:print("all: %s\n", all) + makefile:print(".PHONY: default all %s\n", all) + + -- make it for all targets + for _, target in pairs(project.targets()) do + _make_target(makefile, target, targetflags) + end +end + +-- clean target +function _clean_target(makefile, target) + + -- make head + makefile:printf("clean_%s: ", target:name()) + + -- make dependence for the dependent targets + for _, dep in ipairs(target:get("deps")) do + makefile:write(" clean_" .. dep) + end + + -- make dependence end + makefile:print("") + + -- make body + if not target:isphony() then + + -- remove the target file + _remove(makefile, target:targetfile()) + + -- remove the symbol file + _remove(makefile, target:symbolfile()) + + -- remove the object files + _remove(makefile, target:objectfiles()) + + -- TODO remove the header files (deprecated) + local _, dstheaders = target:headers() + _remove(makefile, dstheaders) + end + + -- make tail + makefile:print("") +end + +-- clean all +function _clean_all(makefile) + + -- clean all + local all = "" + for targetname, _ in pairs(project.targets()) do + all = all .. " clean_" .. targetname + end + makefile:print("clean: %s\n", all) + + -- clean targets + for _, target in pairs(project.targets()) do + _clean_target(makefile, target) + end +end + +-- make +function make(outputdir) + + -- enter project directory + local oldir = os.cd(os.projectdir()) + + -- remove the log makefile first + os.rm(_logfile()) + + -- open the makefile + local makefile = io.open(path.join(outputdir, "makefile"), "w") + + -- make all + _make_all(makefile) + + -- clean all + _clean_all(makefile) + + -- close the makefile + makefile:close() + + -- leave project directory + os.cd(oldir) +end diff --git a/xmake/plugins/project/makefile/makefile.lua b/xmake/plugins/project/makefile/makefile.lua deleted file mode 100644 index 9e2f2a51d..000000000 --- a/xmake/plugins/project/makefile/makefile.lua +++ /dev/null @@ -1,532 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- Licensed to the Apache Software Foundation (ASF) under one --- or more contributor license agreements. See the NOTICE file --- distributed with this work for additional information --- regarding copyright ownership. The ASF licenses this file --- to you under the Apache License, Version 2.0 (the --- "License"); you may not use this file except in compliance --- with the License. You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- Copyright (C) 2015 - 2019, TBOOX Open Source Group. --- --- @author ruki --- @file makefile.lua --- - --- imports -import("core.tool.compiler") -import("core.project.project") -import("core.language.language") -import("core.platform.platform") - --- get log makefile -function _logfile() - - -- get it - return vformat("$(buildir)/.build.log") -end - --- mkdir directory -function _mkdir(makefile, dir) - - if is_plat("windows") then - makefile:print("\t-@mkdir %s > NUL 2>&1", dir) - else - makefile:print("\t@mkdir -p %s", dir) - end -end - --- copy file -function _cp(makefile, sourcefile, targetfile) - - -- copy file - if is_plat("windows") then - makefile:print("\t@copy /Y %s %s > NUL 2>&1", sourcefile, targetfile) - else - makefile:print("\t@cp %s %s", sourcefile, targetfile) - end -end - --- try to remove the given file or directory -function _tryrm(makefile, filedir) - - -- remove it - if is_plat("windows") then - if os.isdir(filedir) then - makefile:print("\t@rmdir /S /Q %s > NUL 2>&1", filedir) - elseif os.isfile(filedir) then - makefile:print("\t@del /F /Q %s > NUL 2>&1", filedir) - end - else - if os.isdir(filedir) then - makefile:print("\t@rm -rf %s", filedir) - elseif os.isfile(filedir) then - makefile:print("\t@rm -f %s", filedir) - end - end -end - --- remove the given files or directories -function _remove(makefile, filedirs) - for _, filedir in ipairs(filedirs) do - _tryrm(makefile, filedir) - end -end - --- make common flags -function _make_common_flags(target, sourcekind, sourcebatch) - - -- make source flags - local sourceflags = {} - local flags_stats = {} - local files_count = 0 - local first_flags = nil - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - - -- make compiler flags - local flags = compiler.compflags(sourcefile, {target = target, sourcekind = sourcekind}) - for _, flag in ipairs(flags) do - flags_stats[flag] = (flags_stats[flag] or 0) + 1 - end - - -- update files count - files_count = files_count + 1 - - -- save first flags - if first_flags == nil then - first_flags = flags - end - - -- save source flags - sourceflags[sourcefile] = flags - end - - -- make common flags - local commonflags = {} - for _, flag in ipairs(first_flags) do - if flags_stats[flag] == files_count then - table.insert(commonflags, flag) - end - end - - -- remove common flags from source flags - local sourceflags_ = {} - for sourcefile, flags in pairs(sourceflags) do - local otherflags = {} - for _, flag in ipairs(flags) do - if flags_stats[flag] ~= files_count then - table.insert(otherflags, flag) - end - end - sourceflags_[sourcefile] = otherflags - end - - -- ok? - return commonflags, sourceflags_ -end - --- make the object for the *.[o|obj] source file -function _make_object_for_object(makefile, target, sourcefile, objectfile) - - -- make command - local cmd = format("xmake l cp %s %s", sourcefile, objectfile) - - -- make head - makefile:printf("%s:", objectfile) - - -- make dependence - makefile:print(" %s", sourcefile) - - -- make body - makefile:print("\t@echo inserting.$(mode) %s", sourcefile) - makefile:print("\t@%s", cmd) - - -- make tail - makefile:print("") - -end - --- make the object for the *.[a|lib] source file -function _make_object_for_static(makefile, target, sourcefile, objectfile) - - -- not supported - raise("source file: %s not supported!", sourcefile) -end - --- make the object -function _make_object(makefile, target, sourcefile, objectfile, sourceflags) - - -- get the source file kind - local sourcekind = language.sourcekind_of(sourcefile) - - -- make the object for the *.o/obj source makefile - if sourcekind == "obj" then - return _make_object_for_object(makefile, target, sourcefile, objectfile) - -- make the object for the *.[a|lib] source file - elseif sourcekind == "lib" then - return _make_object_for_static(makefile, target, sourcefile, objectfile) - end - - -- get program - local program = platform.tool(sourcekind) - - -- get complier flags - local compflags = sourceflags[sourcefile] - - -- make command - local macro = "$(" .. target:name() .. '_' .. sourcekind:upper() .. ")" - local command = compiler.compcmd(sourcefile, objectfile, {compflags = table.join(macro, compflags)}) - - -- replace program to $(XX) - local p, e = command:find("\"" .. program .. "\"", 1, true) - if not p then - p, e = command:find(program, 1, true) - end - if p then - command = format("%s$(%s)%s", command:sub(1, p - 1), sourcekind:upper(), command:sub(e + 1)) - end - - -- replace ccache to $(CCACHE) - local ccache = false - p, e = command:find("ccache", 1, true) - if p then - command = format("%s$(%s)%s", command:sub(1, p - 1), "CCACHE", command:sub(e + 1)) - ccache = true - end - - -- make head - makefile:printf("%s:", objectfile) - - -- make dependence - makefile:print(" %s", sourcefile) - - -- make body - makefile:print("\t@echo %scompiling.$(mode) %s", ifelse(ccache, "ccache ", ""), sourcefile) - _mkdir(makefile, path.directory(objectfile)) - makefile:writef("\t@%s > %s 2>&1\n", command, _logfile()) - - -- make tail - makefile:print("") -end - --- make each objects -function _make_each_objects(makefile, target, sourcekind, sourcebatch, sourceflags) - - -- make them - for index, objectfile in ipairs(sourcebatch.objectfiles) do - _make_object(makefile, target, sourcebatch.sourcefiles[index], objectfile, sourceflags) - end -end - --- make single object -function _make_single_object(makefile, target, sourcekind, sourcebatch, sourceflags) - - -- get source and object files - local sourcefiles = sourcebatch.sourcefiles - local objectfiles = sourcebatch.objectfiles - local dependfiles = sourcebatch.dependfiles - - -- get program - local program = platform.tool(sourcekind) - - -- make command - local macro = "$(" .. target:name() .. '_' .. sourcekind:upper() .. ")" - local command = compiler.compcmd(sourcefiles, objectfiles, {compflags = macro}) - - -- replace program to $(XX) - local p, e = command:find(program, 1, true) - if p then - command = format("%s$(%s)%s", command:sub(1, p - 1), sourcekind:upper(), command:sub(e + 1)) - end - - -- replace ccache to $(CCACHE) - local ccache = false - p, e = command:find("ccache", 1, true) - if p then - command = format("%s$(%s)%s", command:sub(1, p - 1), "CCACHE", command:sub(e + 1)) - ccache = true - end - - -- make head - makefile:printf("%s:", objectfiles) - - -- make dependence - for _, sourcefile in ipairs(sourcefiles) do - makefile:printf(" %s", sourcefile) - end - makefile:print("") - - -- make body - for _, sourcefile in ipairs(sourcefiles) do - makefile:print("\t@echo %scompiling.$(mode) %s", ifelse(ccache, "ccache ", ""), sourcefile) - end - _mkdir(makefile, path.directory(objectfiles)) - makefile:writef("\t@%s > %s 2>&1\n", command, _logfile()) - - -- make tail - makefile:print("") -end - --- make phony -function _make_phony(makefile, target) - - -- make dependence for the dependent targets - makefile:printf("%s:", target:name()) - for _, dep in ipairs(target:get("deps")) do - makefile:write(" " .. dep) - end - makefile:print("") -end - --- make target -function _make_target(makefile, target, targetflags) - - -- is phony target? - if target:isphony() then - return _make_phony(makefile, target) - end - - -- make head - local targetfile = target:targetfile() - makefile:print("%s: %s", target:name(), targetfile) - makefile:printf("%s:", targetfile) - - -- make dependence for the dependent targets - for _, dep in ipairs(target:get("deps")) do - makefile:write(" " .. project.target(dep):targetfile()) - end - - -- make dependence for objects - local objectfiles = target:objectfiles() - for _, objectfile in ipairs(objectfiles) do - makefile:write(" " .. objectfile) - end - - -- make dependence end - makefile:print("") - - -- get linker kind - local linkerkind = target:linker():kind() - - -- get program - local program = platform.tool(linkerkind) - - -- get command - local command = target:linkcmd() - - -- replace linkflags to $(XX) - local p, e = command:find(os.args(target:linkflags()), 1, true) - if p then - command = format("%s$(%s_%s)%s", command:sub(1, p - 1), target:name(), (linkerkind:upper():gsub('%-', '_')), command:sub(e + 1)) - end - - -- replace program to $(XX) - p, e = command:find("\"" .. program .. "\"", 1, true) - if not p then - p, e = command:find(program, 1, true) - end - if p then - command = format("%s$(%s)%s", command:sub(1, p - 1), (linkerkind:upper():gsub('%-', '_')), command:sub(e + 1)) - end - - -- make body - makefile:print("\t@echo linking.$(mode) %s", path.filename(targetfile)) - _mkdir(makefile, path.directory(targetfile)) - makefile:writef("\t@%s > %s 2>&1\n", command, _logfile()) - - -- TODO make header directories (deprecated) - local dstheaderdirs = {} - local srcheaders, dstheaders = target:headerfiles() - for _, dstheader in ipairs(dstheaders) do - dstheaderdirs[path.directory(dstheader)] = true - end - for dstheaderdir, _ in pairs(dstheaderdirs) do - _mkdir(makefile, dstheaderdir) - end - - -- copy headers - if srcheaders and dstheaders then - local i = 1 - for _, srcheader in ipairs(srcheaders) do - local dstheader = dstheaders[i] - if dstheader then - _cp(makefile, srcheader, dstheader) - end - i = i + 1 - end - end - - -- make tail - makefile:print("") - - -- build source batches - for sourcekind, sourcebatch in pairs(target:sourcebatches()) do - if not sourcebatch.rulename then - -- compile source files to single object at once - local sourceflags = targetflags[target:name() .. '_' .. sourcekind:upper()] - if type(sourcebatch.objectfiles) == "string" then - _make_single_object(makefile, target, sourcekind, sourcebatch, sourceflags) - else - _make_each_objects(makefile, target, sourcekind, sourcebatch, sourceflags) - end - end - end -end - --- make all -function _make_all(makefile) - - -- make variables for ccache - makefile:print("CCACHE=ccache") - - -- make variables for source kinds - for sourcekind, _ in pairs(language.sourcekinds()) do - local program = platform.tool(sourcekind) - if program and program ~= "" then - makefile:print("%s=%s", sourcekind:upper(), program) - end - end - makefile:print("") - - -- make variables for linker kinds - local linkerkinds = {} - for _, _linkerkinds in pairs(language.targetkinds()) do - table.join2(linkerkinds, _linkerkinds) - end - for _, linkerkind in ipairs(table.unique(linkerkinds)) do - local program = platform.tool(linkerkind) - if program and program ~= "" then - makefile:print("%s=%s", (linkerkind:upper():gsub('%-', '_')), program) - end - end - makefile:print("") - - -- TODO - -- disable precompiled header first - for _, target in pairs(project.targets()) do - target:set("pcheader", nil) - target:set("pcxxheader", nil) - end - - -- make variables for target flags - local targetflags = {} - for targetname, target in pairs(project.targets()) do - if not target:isphony() then - for sourcekind, sourcebatch in pairs(target:sourcebatches()) do - if not sourcebatch.rulename then - local commonflags, sourceflags = _make_common_flags(target, sourcekind, sourcebatch) - makefile:print("%s_%s=%s", targetname, sourcekind:upper(), os.args(commonflags)) - targetflags[targetname .. '_' .. sourcekind:upper()] = sourceflags - end - end - makefile:print("%s_%s=%s", targetname, target:linker():kind():upper(), os.args(target:linkflags())) - end - end - makefile:print("") - - -- make all - local default = "" - for targetname, target in pairs(project.targets()) do - local isdefault = target:get("default") - if isdefault == nil or isdefault == true then - default = default .. " " .. targetname - end - end - makefile:print("default: %s\n", default) - local all = "" - for targetname, _ in pairs(project.targets()) do - all = all .. " " .. targetname - end - makefile:print("all: %s\n", all) - makefile:print(".PHONY: default all %s\n", all) - - -- make it for all targets - for _, target in pairs(project.targets()) do - _make_target(makefile, target, targetflags) - end -end - --- clean target -function _clean_target(makefile, target) - - -- make head - makefile:printf("clean_%s: ", target:name()) - - -- make dependence for the dependent targets - for _, dep in ipairs(target:get("deps")) do - makefile:write(" clean_" .. dep) - end - - -- make dependence end - makefile:print("") - - -- make body - if not target:isphony() then - - -- remove the target file - _remove(makefile, target:targetfile()) - - -- remove the symbol file - _remove(makefile, target:symbolfile()) - - -- remove the object files - _remove(makefile, target:objectfiles()) - - -- TODO remove the header files (deprecated) - local _, dstheaders = target:headers() - _remove(makefile, dstheaders) - end - - -- make tail - makefile:print("") -end - --- clean all -function _clean_all(makefile) - - -- clean all - local all = "" - for targetname, _ in pairs(project.targets()) do - all = all .. " clean_" .. targetname - end - makefile:print("clean: %s\n", all) - - -- clean targets - for _, target in pairs(project.targets()) do - _clean_target(makefile, target) - end -end - --- make -function make(outputdir) - - -- enter project directory - local oldir = os.cd(os.projectdir()) - - -- remove the log makefile first - os.rm(_logfile()) - - -- open the makefile - local makefile = io.open(path.join(outputdir, "makefile"), "w") - - -- make all - _make_all(makefile) - - -- clean all - _clean_all(makefile) - - -- close the makefile - makefile:close() - - -- leave project directory - os.cd(oldir) -end -- cgit v1.3.1