diff options
| author | OpportunityLiu <[email protected]> | 2019-07-02 13:58:28 +0800 |
|---|---|---|
| committer | OpportunityLiu <[email protected]> | 2019-07-02 13:58:28 +0800 |
| commit | 0b9ed8ef1139530d732331d65280ef003213cc09 (patch) | |
| tree | 0423c8f6a21132ec7141289d80bec009491835a4 | |
| parent | 7d43ca494348e21400285c86be66872adb7e54d8 (diff) | |
| parent | db0b2ae6096ea05dc990ac7d975e194cca75035e (diff) | |
merge dev
| -rw-r--r-- | CHANGELOG.md | 10 | ||||
| -rw-r--r-- | tests/projects/c++/protobuf/src/main.cpp | 10 | ||||
| -rw-r--r-- | tests/projects/c++/protobuf/src/test.proto | 8 | ||||
| -rw-r--r-- | tests/projects/c++/protobuf/xmake.lua | 23 | ||||
| -rw-r--r-- | tests/projects/c/protobuf/src/main.c | 7 | ||||
| -rw-r--r-- | tests/projects/c/protobuf/src/test.proto | 8 | ||||
| -rw-r--r-- | tests/projects/c/protobuf/xmake.lua | 20 | ||||
| -rw-r--r-- | xmake/actions/require/impl/action/patch.lua | 2 | ||||
| -rw-r--r-- | xmake/core/base/os.lua | 58 | ||||
| -rw-r--r-- | xmake/core/project/target.lua | 27 | ||||
| -rw-r--r-- | xmake/rules/protobuf/proto.lua | 116 | ||||
| -rw-r--r-- | xmake/rules/protobuf/xmake.lua | 42 |
12 files changed, 295 insertions, 36 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d0bcdb32..40f0cd4ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## master (unreleased) +### New features + +* Add protobuf c/c++ rules +* [#468](https://github.com/xmake-io/xmake/pull/468)Add utf-8 support for windows + ## v2.2.7 ### New features @@ -603,6 +608,11 @@ ## master (开发中) +### 新特性 + +* 添加protobuf c/c++构建规则 +* [#468](https://github.com/xmake-io/xmake/pull/468)添加对 Windows 的 UTF-8 支持 + ## v2.2.7 ### 新特性 diff --git a/tests/projects/c++/protobuf/src/main.cpp b/tests/projects/c++/protobuf/src/main.cpp new file mode 100644 index 000000000..1e7830c17 --- /dev/null +++ b/tests/projects/c++/protobuf/src/main.cpp @@ -0,0 +1,10 @@ +#include <iostream> +#include "test.pb.h" + +using namespace std; + +int main(int argc, char** argv) +{ + cout << "hello world!" << endl; + return 0; +} diff --git a/tests/projects/c++/protobuf/src/test.proto b/tests/projects/c++/protobuf/src/test.proto new file mode 100644 index 000000000..0f129ea13 --- /dev/null +++ b/tests/projects/c++/protobuf/src/test.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; +package test; +message TestCase { + string name = 4; +} +message Test { + repeated TestCase case = 1; +} diff --git a/tests/projects/c++/protobuf/xmake.lua b/tests/projects/c++/protobuf/xmake.lua new file mode 100644 index 000000000..da8f1ee16 --- /dev/null +++ b/tests/projects/c++/protobuf/xmake.lua @@ -0,0 +1,23 @@ + +-- add rules: debug and release +add_rules("mode.debug", "mode.release") + +-- add protobuf +add_requires("protobuf-cpp") + +-- add target +target("console_c++") + + -- set kind + set_kind("binary") + + -- set languages + set_languages("c++11") + + -- add packages + add_packages("protobuf-cpp") + + -- add files + add_files("src/*.cpp") + add_files("src/*.proto", {rules = "protobuf.cpp"}) + diff --git a/tests/projects/c/protobuf/src/main.c b/tests/projects/c/protobuf/src/main.c new file mode 100644 index 000000000..1f0458b66 --- /dev/null +++ b/tests/projects/c/protobuf/src/main.c @@ -0,0 +1,7 @@ +#include <stdio.h> +#include "test.pb-c.h" + +int main(int argc, char** argv) +{ + return 0; +} diff --git a/tests/projects/c/protobuf/src/test.proto b/tests/projects/c/protobuf/src/test.proto new file mode 100644 index 000000000..0f129ea13 --- /dev/null +++ b/tests/projects/c/protobuf/src/test.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; +package test; +message TestCase { + string name = 4; +} +message Test { + repeated TestCase case = 1; +} diff --git a/tests/projects/c/protobuf/xmake.lua b/tests/projects/c/protobuf/xmake.lua new file mode 100644 index 000000000..151acf5b4 --- /dev/null +++ b/tests/projects/c/protobuf/xmake.lua @@ -0,0 +1,20 @@ + +-- add rules: debug and release +add_rules("mode.debug", "mode.release") + +-- add protobuf +add_requires("protobuf-c") + +-- add target +target("console_c") + + -- set kind + set_kind("binary") + + -- add packages + add_packages("protobuf-c") + + -- add files + add_files("src/*.c") + add_files("src/*.proto", {rules = "protobuf.c"}) + diff --git a/xmake/actions/require/impl/action/patch.lua b/xmake/actions/require/impl/action/patch.lua index bab50f9c5..cde52ec12 100644 --- a/xmake/actions/require/impl/action/patch.lua +++ b/xmake/actions/require/impl/action/patch.lua @@ -30,7 +30,7 @@ function _patch(package, patch_url, patch_hash) vprint("patching %s to %s-%s ..", patch_url, package:name(), package:version_str()) -- get the patch file - local patch_file = path.join(os.tmpdir(), "patches", package:name(), package:version_str(), path.filename(patch_url)) + local patch_file = path.join(os.tmpdir(), "patches", package:name(), package:version_str(), (path.filename(patch_url):gsub("%?.+$", ""))) -- the package file have been downloaded? local cached = true diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index ae04bf49f..ee5979b2e 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -792,42 +792,36 @@ end -- get the system null device function os.nuldev(input) - if os.host() == "windows" then - -- not every program supports windows NUL device - -- we use a disk file to simulate it - - -- init the output nuldev - if xmake._NULDEV_OUTPUT == nil then - xmake._NULDEV_OUTPUT = path.join(path.directory(os.tmpdir()), "null") + if input then + if os.host() == "windows" then + -- init the input nuldev + if xmake._NULDEV_INPUT == nil then + -- create an empty file + -- + -- for fix issue on mingw: + -- $ gcc -fopenmp -S -o nul -xc nul + -- gcc: fatal error:input file 'nul' is the same as output file + -- + local inputfile = os.tmpfile() + io.writefile(inputfile, "") + xmake._NULDEV_INPUT = inputfile + end else - os.rm(xmake._NULDEV_OUTPUT) - end - -- init the input nuldev - if xmake._NULDEV_INPUT == nil then - -- create an empty file - -- - -- for fix issue on mingw: - -- $ gcc -fopenmp -S -o nul -xc nul - -- gcc: fatal error:input file ‘nul’ is the same as output file - -- - local inputfile = path.join(path.directory(os.tmpdir()), "nullin") - io.writefile(inputfile, "") - xmake._NULDEV_INPUT = inputfile - end - else - if xmake._NULDEV_OUTPUT == nil then - xmake._NULDEV_OUTPUT = "/dev/null" - end - if xmake._NULDEV_INPUT == nil then - xmake._NULDEV_INPUT = "/dev/null" + if xmake._NULDEV_INPUT == nil then + xmake._NULDEV_INPUT = "/dev/null" + end end - end - - -- get nuldev - if input then return xmake._NULDEV_INPUT else - return xmake._NULDEV_OUTPUT + if os.host() == "windows" then + -- @note cannot cache this file path to avoid multi-processes writing to the same file at the same time + return os.tmpfile() + else + if xmake._NULDEV_OUTPUT == nil then + xmake._NULDEV_OUTPUT = "/dev/null" + end + return xmake._NULDEV_OUTPUT + end end end diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 1745e08a4..a4c194a15 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -90,8 +90,8 @@ function _instance:_load_rules(suffix) return true end --- do load target and rules -function _instance:_load() +-- load all +function _instance:_load_all() -- do before_load with target rules local ok, errors = self:_load_rules("before") @@ -119,8 +119,29 @@ function _instance:_load() if not ok then return false, errors end + return true +end - -- ok +-- do load target and rules +function _instance:_load() + + -- enter the environments of the target packages + local oldenvs = {} + for name, values in pairs(self:pkgenvs()) do + oldenvs[name] = os.getenv(name) + os.addenv(name, unpack(values)) + end + + -- load all + local ok, errors = self:_load_all() + if not ok then + return false, errors + end + + -- leave the environments of the target packages + for name, values in pairs(oldenvs) do + os.setenv(name, values) + end return true end diff --git a/xmake/rules/protobuf/proto.lua b/xmake/rules/protobuf/proto.lua new file mode 100644 index 000000000..41ae6a388 --- /dev/null +++ b/xmake/rules/protobuf/proto.lua @@ -0,0 +1,116 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed 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 proto.lua +-- + +-- imports +import("core.base.option") +import("core.theme.theme") +import("core.project.config") +import("core.project.depend") +import("core.tool.compiler") +import("lib.detect.find_tool") + +-- build protobuf file +function main(target, sourcekind, sourcefile_proto, opt) + + -- find protoc + local protoc = target:data("protobuf.protoc") + if not protoc and sourcekind == "cxx" then + protoc = find_tool("protoc") + if protoc and protoc.program then + target:data_set("protobuf.protoc", protoc.program) + end + end + + -- find protoc-c + local protoc_c = target:data("protobuf.protoc-c") + if not protoc_c and sourcekind == "cc" then + protoc_c = find_tool("protoc-c") or protoc + if protoc_c and protoc_c.program then + target:data_set("protobuf.protoc-c", protoc_c.program) + end + end + + -- get protoc + protoc = assert(target:data(sourcekind == "cxx" and "protobuf.protoc" or "protobuf.protoc-c"), "protoc not found!") + + -- get c/c++ source file for protobuf + local sourcefile_cx = path.join(target:autogendir(), "rules", "protobuf", path.basename(sourcefile_proto) .. ".pb" .. (sourcekind == "cxx" and ".cc" or "-c.c")) + local sourcefile_dir = path.directory(sourcefile_cx) + + -- add includedirs + target:add("includedirs", sourcefile_dir) + + -- get object file + local objectfile = target:objectfile(sourcefile_cx) + + -- load compiler + local compinst = compiler.load(sourcekind, {target = target}) + + -- get compile flags + local configs = {includedirs = sourcefile_dir} + if sourcekind == "cxx" then + configs.languages = "c++11" + end + local compflags = compinst:compflags({target = target, sourcefile = sourcefile_cx, configs = configs}) + + -- add objectfile + table.insert(target:objectfiles(), objectfile) + + -- load dependent info + local dependfile = target:dependfile(objectfile) + local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {}) + + -- need build this object? + local depvalues = {compinst:program(), compflags} + if not depend.is_changed(dependinfo, {lastmtime = os.mtime(objectfile), values = depvalues}) then + return + end + + -- trace progress info + cprintf("${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} ", opt.progress) + if option.get("verbose") then + cprint("${dim color.build.object}compiling.proto %s", sourcefile_proto) + else + cprint("${color.build.object}compiling.proto %s", sourcefile_proto) + end + + -- ensure the source file directory + if not os.isdir(sourcefile_dir) then + os.mkdir(sourcefile_dir) + end + + -- compile protobuf + os.vrunv(protoc, {sourcefile_proto, "-I" .. os.args(path.directory(sourcefile_proto)), (sourcekind == "cxx" and "--cpp_out=" or "--c_out=") .. sourcefile_dir}) + + -- trace + if option.get("verbose") then + print(compinst:compcmd(sourcefile_cx, objectfile, {compflags = compflags})) + end + + -- compile c/c++ source file for protobuf + dependinfo.files = {} + assert(compinst:compile(sourcefile_cx, objectfile, {dependinfo = dependinfo, compflags = compflags})) + + -- update files and values to the dependent file + dependinfo.values = depvalues + table.insert(dependinfo.files, sourcefile_proto) + depend.save(dependinfo, dependfile) +end + diff --git a/xmake/rules/protobuf/xmake.lua b/xmake/rules/protobuf/xmake.lua new file mode 100644 index 000000000..1447e2b05 --- /dev/null +++ b/xmake/rules/protobuf/xmake.lua @@ -0,0 +1,42 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed 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 xmake.lua +-- + +-- define rule: protobuf.cpp +rule("protobuf.cpp") + + -- set extension + set_extensions(".proto") + + -- build protobuf file + before_build_file(function (target, sourcefile_proto, opt) + import("proto")(target, "cxx", sourcefile_proto, opt) + end) + + +-- define rule: protobuf.c +rule("protobuf.c") + + -- set extension + set_extensions(".proto") + + -- build protobuf file + before_build_file(function (target, sourcefile_proto, opt) + import("proto")(target, "cc", sourcefile_proto, opt) + end) |
