improve directory creator to support same functionality as 'mkdir -p'
This commit is contained in:
parent
f9e055c551
commit
1fb37f4c71
|
@ -3,6 +3,7 @@
|
|||
* in OpenFPGA framework
|
||||
*******************************************************************/
|
||||
#include <sys/stat.h>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
|
@ -117,37 +118,121 @@ std::string find_path_dir_name(const std::string& file_name) {
|
|||
/********************************************************************
|
||||
* Create a directory with a given path
|
||||
********************************************************************/
|
||||
bool create_dir_path(const char* dir_path) {
|
||||
/* Give up if the path is empty */
|
||||
if (nullptr == dir_path) {
|
||||
VTR_LOG_ERROR("dir_path is empty and nothing is created.\n");
|
||||
return false;
|
||||
}
|
||||
static
|
||||
bool create_dir_path(const std::string& dir_path,
|
||||
const bool& verbose) {
|
||||
/* Give up if the path is empty */
|
||||
if (true == dir_path.empty()) {
|
||||
VTR_LOG_ERROR("Directory path is empty and nothing will be created.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Try to create a directory */
|
||||
int ret = mkdir(dir_path, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH);
|
||||
/* Try to create a directory */
|
||||
int ret = mkdir(dir_path.c_str(), S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH);
|
||||
|
||||
/* Analyze the return flag and output status */
|
||||
switch (ret) {
|
||||
case 0:
|
||||
VTR_LOG("Succeed to create directory '%s'\n",
|
||||
dir_path);
|
||||
return true;
|
||||
case -1:
|
||||
if (EEXIST == errno) {
|
||||
VTR_LOG_WARN("Directory '%s' already exists. Will overwrite contents\n",
|
||||
dir_path);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
VTR_LOG_ERROR("Create directory '%s'...Failed!\n",
|
||||
dir_path);
|
||||
exit(1);
|
||||
return false;
|
||||
/* Analyze the return flag and output status */
|
||||
switch (ret) {
|
||||
case 0:
|
||||
VTR_LOGV(verbose,
|
||||
"Succeed to create directory '%s'\n",
|
||||
dir_path.c_str());
|
||||
return true;
|
||||
case -1:
|
||||
if (EEXIST == errno) {
|
||||
VTR_LOGV_WARN(verbose,
|
||||
"Directory '%s' already exists. Will overwrite contents\n",
|
||||
dir_path.c_str());
|
||||
return true;
|
||||
}
|
||||
VTR_LOG_ERROR("Create directory '%s'...Failed!\n",
|
||||
dir_path.c_str());
|
||||
exit(1);
|
||||
break;
|
||||
default:
|
||||
VTR_LOG_ERROR("Create directory '%s'...Failed!\n",
|
||||
dir_path.c_str());
|
||||
exit(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Recursively create a directory with a given path
|
||||
* The create_dir_path() function will only try to create a directory
|
||||
* in the last level. If any parent directory is not created, it will
|
||||
* always fail.
|
||||
* This function will try to create all the parent directory before
|
||||
* creating the last level.
|
||||
********************************************************************/
|
||||
static
|
||||
bool rec_create_dir_path(const std::string& dir_path) {
|
||||
/* Give up if the path is empty */
|
||||
if (true == dir_path.empty()) {
|
||||
VTR_LOG_ERROR("Directory path is empty and nothing will be created.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Try to find the positions of all the slashes
|
||||
* which are the splitter between directories
|
||||
*/
|
||||
char back_slash = '/';
|
||||
|
||||
#ifdef _WIN32
|
||||
/* For windows OS, replace any '/' with '\' */
|
||||
char back_slash = '\\';
|
||||
#endif
|
||||
|
||||
std::vector<size_t> slash_pos;
|
||||
|
||||
/* Keep searching until we reach the end of the string */
|
||||
for (size_t pos = 0; pos < dir_path.size(); ++pos) {
|
||||
/* Skip the pos = 0, we should avoid creating any root directory */
|
||||
if ( (back_slash == dir_path.at(pos))
|
||||
&& (0 != pos)) {
|
||||
slash_pos.push_back(pos);
|
||||
}
|
||||
}
|
||||
|
||||
/* Create directory by following the position of back slash
|
||||
* For each back slash, create a sub string from the beginning
|
||||
* and try to create directory
|
||||
*/
|
||||
for (const size_t& pos : slash_pos) {
|
||||
std::string sub_dir = dir_path.substr(0, pos);
|
||||
|
||||
/* Turn on verbose output only for the last position: the leaf directory */
|
||||
if (false == create_dir_path(sub_dir, &pos == &slash_pos.back())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Top function to create a directory with a given path
|
||||
* Allow users to select if use the recursive way or not
|
||||
*
|
||||
* Strongly recommend to use the recursive way, as it can maximum
|
||||
* guarantee the success in creation of directories
|
||||
********************************************************************/
|
||||
void create_directory(const std::string& dir_path, const bool& recursive) {
|
||||
std::string formatted_dir_path = format_dir_path(dir_path);
|
||||
bool status = false;
|
||||
|
||||
if (true == recursive) {
|
||||
status = rec_create_dir_path(formatted_dir_path);
|
||||
} else {
|
||||
status = create_dir_path(formatted_dir_path, true);
|
||||
}
|
||||
|
||||
if (false == status) {
|
||||
VTR_LOG_ERROR("Fail to create directory '%s'\n",
|
||||
formatted_dir_path.c_str());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
|
|
|
@ -23,7 +23,7 @@ std::string find_path_file_name(const std::string& file_name);
|
|||
|
||||
std::string find_path_dir_name(const std::string& file_name);
|
||||
|
||||
bool create_dir_path(const char* dir_path);
|
||||
void create_directory(const std::string& dir_path, const bool& recursive = true);
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ void write_device_rr_gsb_to_xml(const char* sb_xml_dir,
|
|||
std::string xml_dir_name = format_dir_path(std::string(sb_xml_dir));
|
||||
|
||||
/* Create directories */
|
||||
create_dir_path(xml_dir_name.c_str());
|
||||
create_directory(xml_dir_name);
|
||||
|
||||
vtr::Point<size_t> sb_range = device_rr_gsb.get_gsb_range();
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ void fpga_bitstream(OpenfpgaContext& openfpga_ctx,
|
|||
std::string src_dir_path = find_path_dir_name(cmd_context.option_value(cmd, opt_file));
|
||||
|
||||
/* Create directories */
|
||||
create_dir_path(src_dir_path.c_str());
|
||||
create_directory(src_dir_path);
|
||||
|
||||
write_arch_independent_bitstream_to_xml_file(openfpga_ctx.bitstream_manager(),
|
||||
cmd_context.option_value(cmd, opt_file));
|
||||
|
|
|
@ -42,7 +42,7 @@ void write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
|
|||
std::string sdc_dir_path = format_dir_path(cmd_context.option_value(cmd, opt_output_dir));
|
||||
|
||||
/* Create directories */
|
||||
create_dir_path(sdc_dir_path.c_str());
|
||||
create_directory(sdc_dir_path);
|
||||
|
||||
PnrSdcOption options(sdc_dir_path);
|
||||
|
||||
|
@ -96,7 +96,7 @@ void write_analysis_sdc(OpenfpgaContext& openfpga_ctx,
|
|||
std::string sdc_dir_path = format_dir_path(cmd_context.option_value(cmd, opt_output_dir));
|
||||
|
||||
/* Create directories */
|
||||
create_dir_path(sdc_dir_path.c_str());
|
||||
create_directory(sdc_dir_path);
|
||||
|
||||
AnalysisSdcOption options(sdc_dir_path);
|
||||
options.set_generate_sdc_analysis(true);
|
||||
|
|
|
@ -63,19 +63,19 @@ void fpga_fabric_verilog(ModuleManager& module_manager,
|
|||
std::string src_dir_path = format_dir_path(options.output_directory());
|
||||
|
||||
/* Create directories */
|
||||
create_dir_path(src_dir_path.c_str());
|
||||
create_directory(src_dir_path);
|
||||
|
||||
/* Sub directory under SRC directory to contain all the primitive block netlists */
|
||||
std::string submodule_dir_path = src_dir_path + std::string(DEFAULT_SUBMODULE_DIR_NAME);
|
||||
create_dir_path(submodule_dir_path.c_str());
|
||||
create_directory(submodule_dir_path);
|
||||
|
||||
/* Sub directory under SRC directory to contain all the logic block netlists */
|
||||
std::string lb_dir_path = src_dir_path + std::string(DEFAULT_LB_DIR_NAME);
|
||||
create_dir_path(lb_dir_path.c_str());
|
||||
create_directory(lb_dir_path);
|
||||
|
||||
/* Sub directory under SRC directory to contain all the routing block netlists */
|
||||
std::string rr_dir_path = src_dir_path + std::string(DEFAULT_RR_DIR_NAME);
|
||||
create_dir_path(rr_dir_path.c_str());
|
||||
create_directory(rr_dir_path);
|
||||
|
||||
/* Print Verilog files containing preprocessing flags */
|
||||
print_verilog_preprocessing_flags_netlist(std::string(src_dir_path),
|
||||
|
@ -153,7 +153,7 @@ void fpga_verilog_testbench(const ModuleManager& module_manager,
|
|||
std::string netlist_name = atom_ctx.nlist.netlist_name();
|
||||
|
||||
/* Create directories */
|
||||
create_dir_path(src_dir_path.c_str());
|
||||
create_directory(src_dir_path);
|
||||
|
||||
/* TODO: check if this works here. This function was in fabric generator */
|
||||
print_verilog_simulation_preprocessing_flags(std::string(src_dir_path),
|
||||
|
|
Loading…
Reference in New Issue