diff --git a/framework/tools/hc-gen/Makefile b/framework/tools/hc-gen/Makefile index e7fde3daee97db60b652e30453423d5fbeede569..4d241fad3a2f9d4b0616ceef28ff1785528c4ef2 100644 --- a/framework/tools/hc-gen/Makefile +++ b/framework/tools/hc-gen/Makefile @@ -9,7 +9,7 @@ BUILD_DIR := build TARGET := $(BUILD_DIR)/hc-gen CXX := c++ -CXX_FLAGS := -std=gnu++14 -s +CXX_FLAGS := -std=gnu++17 -s CXX_LD_FLAGS := -lstdc++ SRCS := $(wildcard src/*.cpp) diff --git a/framework/tools/hc-gen/hc_gen.gni b/framework/tools/hc-gen/hc_gen.gni index b851123eccd1167d2ec9cb584a330105d2834a9f..14f50b00f9c773534f1952f36689686748c36e65 100644 --- a/framework/tools/hc-gen/hc_gen.gni +++ b/framework/tools/hc-gen/hc_gen.gni @@ -27,6 +27,10 @@ template("hc_gen") { target(target_type, target_name) { deps = [ "//drivers/hdf_core/framework/tools/hc-gen:build_hc_gen" ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + script = "/usr/bin/env" if (defined(ohos_lite)) { script = "//build/lite/run_shell_cmd.py" @@ -56,6 +60,10 @@ template("hc_gen") { output_suffix = ".hcb" } + if (defined(invoker.extra_flags)) { + hc_flags += invoker.extra_flags + } + if (defined(invoker.outputs)) { outputs = invoker.outputs } else { @@ -69,6 +77,21 @@ template("hc_gen") { } else { src = "{{source}}" } + if (defined(invoker.hc_gen_start_cfg) && invoker.hc_gen_start_cfg) { + is_separate = false + foreach (f, hc_flags) { + if (f == "--separate") { + is_separate = true + } + } + if (is_separate) { + outputs = [] + foreach(o, invoker.outputs) { + outputs += [ string_replace(o, ".cfg", "") ] + } + outputs += invoker.outputs + } + } args = [ rebase_path( get_path_info("//drivers/hdf_core/framework/tools/hc-gen/", diff --git a/framework/tools/hc-gen/src/main.cpp b/framework/tools/hc-gen/src/main.cpp index 91a6625361868b5ab4bc704feaafb2adbcf038c7..b8bef9a1a56b43d3ba9770a1b917053152913bce 100644 --- a/framework/tools/hc-gen/src/main.cpp +++ b/framework/tools/hc-gen/src/main.cpp @@ -18,7 +18,7 @@ using namespace OHOS::Hardware; int main(int argc, char *argv[]) { - auto option = Option::Instance().Parse(argc, argv); + auto& option = Option::Instance().Parse(argc, argv); if (option.OptionError()) { return EFAIL; } diff --git a/framework/tools/hc-gen/src/option.cpp b/framework/tools/hc-gen/src/option.cpp index c661d330176bb4fcf5d0d6754ba6010040bbc7c8..c885c88ed757f09b26cb618bad1150b40b9f231d 100644 --- a/framework/tools/hc-gen/src/option.cpp +++ b/framework/tools/hc-gen/src/option.cpp @@ -57,8 +57,27 @@ Option &Option::Parse(int argc, char **argv) bool Option::ParseOptions(int argc, char **argv) { int32_t op = 0; + + static struct option longOptions[] = { + { "separate", no_argument, 0, 0 }, + { 0, 0, 0, 0 } + }; + while (op != OPTION_END) { - op = getopt(argc, argv, HCS_SUPPORT_ARGS); + int optionIndex = 0; + op = getopt_long(argc, argv, HCS_SUPPORT_ARGS, longOptions, &optionIndex); + // long options process + if (op == 0) { + // --separate option process + if (strcmp(longOptions[optionIndex].name, "separate") == 0) { + if ((genStartCfg_ == true) && (shouldGenByteCodeConfig_ == false)) { + isCfgSeperate_ = true; + } else { + Logger().Error() << "--separate must follow with -s"; + SetOptionError(); + } + } + } SetOptionData(op); if (ShouldShowUsage() || ShouldShowVersion()) { return false; @@ -136,6 +155,8 @@ void Option::ShowUsage() ShowOption("-V", "show verbose info"); ShowOption("-v", "show version"); ShowOption("-h", "show this help message"); + Logger() << " " << "Specific Options:"; + ShowOption("--separate", "output separate config files, must be used with -s"); } void Option::ShowOption(const ::std::string &option, const ::std::string &helpInfo) @@ -199,6 +220,11 @@ bool Option::ShouldGenStartConfig() const return genStartCfg_; } +bool Option::ShouldGenSeparateConfig() const +{ + return isCfgSeperate_; +} + std::string Option::GetSymbolPrefix() const { return symbolNamePrefix_; diff --git a/framework/tools/hc-gen/src/option.h b/framework/tools/hc-gen/src/option.h index db08551c796566dfbbf4635a7df174999ec81662..1a08034007120ec43fc810d90703ee40dc5cf4a9 100644 --- a/framework/tools/hc-gen/src/option.h +++ b/framework/tools/hc-gen/src/option.h @@ -44,6 +44,8 @@ public: bool ShouldGenStartConfig() const; + bool ShouldGenSeparateConfig() const; + bool ShouldGenHexDump() const; bool ShouldDecompile() const; @@ -81,6 +83,7 @@ private: bool shouldDecompile_ = false; bool verboseLog_ = false; bool optionError_ = false; + bool isCfgSeperate_ = false; std::string symbolNamePrefix_; std::string sourceName_; std::string sourceNameBase_; diff --git a/framework/tools/hc-gen/src/startup_cfg_gen.cpp b/framework/tools/hc-gen/src/startup_cfg_gen.cpp index ec219cb9f1f0d754822cd7612c20545369bb15a7..78224c6a8edafe6708a138e054731815976e039e 100644 --- a/framework/tools/hc-gen/src/startup_cfg_gen.cpp +++ b/framework/tools/hc-gen/src/startup_cfg_gen.cpp @@ -13,8 +13,10 @@ #include "ast.h" #include "file.h" #include "logger.h" +#include using namespace OHOS::Hardware; +namespace fs = std::filesystem; static constexpr const char *BOOT_CONFIG_TOP = "{\n" @@ -43,7 +45,15 @@ static constexpr uint32_t INVALID_PRIORITY = 0; static constexpr const char *SAND_BOX_INFO = " \"sandbox\" : "; static constexpr uint32_t INVALID_SAND_BOX = 0xffffffff; static constexpr const char *MALLOPT_SEPARATOR = ":"; -StartupCfgGen::StartupCfgGen(const std::shared_ptr &ast) : Generator(ast) +static constexpr const char *IMPORT_CONFIG_TOP = + "{\n" + " \"import\" : [\n"; +static constexpr const char *IMPORT_CONFIG_BOTTOM = + " ]\n" + "}\n"; +static const std::string ABSOLUTE_INSTALL_PATH = "/chip_prod/etc/init/"; +StartupCfgGen::StartupCfgGen(const std::shared_ptr &ast) : Generator(ast), \ + option(Option::Instance()) { } @@ -58,6 +68,36 @@ void StartupCfgGen::HeaderBottomOutput() ofs_.close(); } +void StartupCfgGen::ImportFileHeaderTopOutput() +{ + // separate mode must generate import file + // ensure the directories exist, generate file in directory + if (!CreatePreDirectory()) { + Logger().Error() << "create generated directories failed" << '\n'; + return; + } + + std::string fileName = outFileName_ + ".cfg"; + + importFile_.open(fileName, std::ofstream::out | std::ofstream::binary); + if (!importFile_.is_open()) { + Logger().Error() << "failed to create import file."; + return; + } + importFile_ << IMPORT_CONFIG_TOP; +} + +void StartupCfgGen::ImportFileHeaderBottomOutput() +{ + importFile_ << IMPORT_CONFIG_BOTTOM; + importFile_.close(); +} + +void StartupCfgGen::InsertImportFilePath(const std::string& filePath) +{ + importFile_ << " \"" << filePath << "\""; +} + bool StartupCfgGen::Output() { if (!Initialize()) { @@ -66,34 +106,24 @@ bool StartupCfgGen::Output() if (!TemplateNodeSeparate()) { return false; } - HeaderTopOutput(); if (!GetHostInfo()) { return false; } HostInfosOutput(); - HeaderBottomOutput(); - return true; } bool StartupCfgGen::Initialize() { - std::string outFileName = Option::Instance().GetOutputName(); - if (outFileName.empty()) { - outFileName = Option::Instance().GetSourceNameBase(); + outFileName_ = option.GetOutputName(); + if (outFileName_.empty()) { + outFileName_ = option.GetSourceNameBase(); } - outFileName = Util::File::StripSuffix(outFileName).append(".cfg"); - outFileName_ = Util::File::FileNameBase(outFileName); + outFileName_ = Util::File::StripSuffix(outFileName_); - ofs_.open(outFileName, std::ofstream::out | std::ofstream::binary); - if (!ofs_.is_open()) { - Logger().Error() << "failed to open output file: " << outFileName; - return false; - } - - Logger().Debug() << "output: " << outFileName << outFileName_ << '\n'; + Logger().Debug() << "outFileName: " << outFileName_ << '\n'; return true; } @@ -250,13 +280,102 @@ void StartupCfgGen::HostInfosOutput() (p1.second.hostId < p2.second.hostId) : (p1.second.hostPriority < p2.second.hostPriority); }); - std::vector>::iterator it = vect.begin(); - for (; it != vect.end(); ++it, ++cnt) { + bool isSeparate = option.ShouldGenSeparateConfig(); + if (isSeparate) { + Logger().Debug() << "separate output"; + HostConfigSeparateOutput(vect); + } else { + HostConfigWholeOutput(vect); + } +} + +void StartupCfgGen::HostConfigWholeOutput(const std::vector> &vect) +{ + bool end = false; + uint32_t cnt = 1; + const uint32_t size = hostInfoMap_.size(); + + // treate as file name + fs::path path = fs::path(outFileName_); + if (!path.parent_path().empty() && !fs::exists(path.parent_path())) { + if (!fs::create_directories(path.parent_path())) { + Logger().Error() << "create parent path failed." << path.parent_path().string(); + return; + } + } + std::string outPutFile = outFileName_.append(".cfg"); + + // Initialize output file + ofs_.open(outPutFile, std::ofstream::out | std::ofstream::binary); + if (!ofs_.is_open()) { + Logger().Error() << "failed to open output file: " << outPutFile; + return; + } + + HeaderTopOutput(); + std::vector>::const_iterator it = vect.cbegin(); + for (; it != vect.cend(); ++it, ++cnt) { if (cnt == size) { end = true; } HostInfoOutput(it->first, end); } + HeaderBottomOutput(); +} + +void StartupCfgGen::HostConfigSeparateOutput(const std::vector> &vect) +{ + // generate import file + ImportFileHeaderTopOutput(); + size_t count = 0; + // generate separate config files + for (auto it = vect.cbegin(); it != vect.cend(); ++it) { + ++count; + std::string fileName = outFileName_.empty() ? it->first : \ + outFileName_ + OS_SEPARATOR + it->first; + + fileName = Util::File::StripSuffix(fileName).append(".cfg"); + ofs_.open(fileName, std::ofstream::out | std::ofstream::binary); + if (!ofs_.is_open()) { + Logger().Error() << "generate " << fileName << " failed"; + continue; + } + HeaderTopOutput(); + HostInfoOutput(it->first, true); + HeaderBottomOutput(); + + std::string relativePath; + if (fs::path(outFileName_).parent_path().empty()) { + relativePath = fileName; + } else { + relativePath = fs::relative(fileName, fs::path(outFileName_).parent_path()).string(); + } + + if (relativePath.empty()) { + continue; + } + + InsertImportFilePath(ABSOLUTE_INSTALL_PATH + relativePath); + if (count != vect.size()) { + importFile_ << ","; + } + importFile_ << "\n"; + } + // import file end + ImportFileHeaderBottomOutput(); +} + +bool StartupCfgGen::CreatePreDirectory() +{ + // generate files in directory + fs::path outPutDir = outFileName_; + if (!outPutDir.empty() && !fs::exists(outPutDir)) { + if (!fs::create_directories(outPutDir)) { + Logger().Error() << "create generated directories failed, dir: " << outPutDir; + return false; + } + } + return true; } void StartupCfgGen::GetConfigArray(const std::shared_ptr &term, std::string &config) diff --git a/framework/tools/hc-gen/src/startup_cfg_gen.h b/framework/tools/hc-gen/src/startup_cfg_gen.h index b8b51dbd7800e3c08169b9a07c537400c13c3131..a03aa6b0f33872017b36547a33331ceb84036eae 100644 --- a/framework/tools/hc-gen/src/startup_cfg_gen.h +++ b/framework/tools/hc-gen/src/startup_cfg_gen.h @@ -15,6 +15,7 @@ #include #include "generator.h" +#include "option.h" namespace OHOS { namespace Hardware { @@ -60,12 +61,24 @@ private: void HostInfoOutput(const std::string &name, bool end); + void HostConfigWholeOutput(const std::vector> &vect); + + void HostConfigSeparateOutput(const std::vector> &vect); + + bool CreatePreDirectory(); + void HeaderTopOutput(); void HeaderBottomOutput(); void HostInfosOutput(); + void ImportFileHeaderTopOutput(); + + void ImportFileHeaderBottomOutput(); + + void InsertImportFilePath(const std::string& filePath); + void EmitDynamicLoad(const std::string &name, std::set &configedKeywords); void EmitPathInfo(const std::string &name, std::set &configedKeywords); @@ -100,6 +113,10 @@ private: std::ofstream ofs_; std::string outFileName_; std::map hostInfoMap_; + + std::ofstream importFile_; + + const OHOS::Hardware::Option& option; }; } // namespace Hardware } // namespace OHOS