Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace boost.filesystem #207

Merged
merged 13 commits into from
May 31, 2018
Merged

Conversation

C0nsultant
Copy link
Member

@C0nsultant C0nsultant commented May 27, 2018

Create a minimally slim replacement for boost.filesystem for WIN32 and
POSIX compliant systems.

Closes #70.

Create a minimally slim replacement for boost.filesystem for WIN32 and
POSIX compliant systems.
@C0nsultant C0nsultant added third party third party libraries that are shipped and/or linked refactoring Boost internal backend labels May 27, 2018
@C0nsultant C0nsultant self-assigned this May 27, 2018
@C0nsultant C0nsultant added this to To do in First Stable Release via automation May 27, 2018
@C0nsultant C0nsultant requested a review from ax3l May 27, 2018 20:19
@C0nsultant C0nsultant moved this from To do to In progress in First Stable Release May 28, 2018
CMakeLists.txt Outdated
@@ -209,6 +210,24 @@ set(IO_SOURCE
src/IO/HDF5/HDF5IOHandler.cpp
src/IO/HDF5/ParallelHDF5IOHandler.cpp)

if(WIN32)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just do #if defined(_WIN32) in-code and assume all others are POSIX.
Ref: https://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor

Copy link
Member

@ax3l ax3l May 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think it's really unsave to set those vars globally and publicly, e.g. in the tests below ;-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will push a commit to fix this...

list_directory(std::string const& path );

void
create_directories( std::string const& path );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docstring: this is mkdir -p, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was the intention, to save the user from creating loops or copy-pasting.

create_directories( std::string const& path );

void
remove_file( std::string const& path );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docstring: this is equivalent to rm with -r or -f or both or none?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this will be implemented with remove(), at least -r.
-f should probably not be the default with void - the user should be notified if the target does not exist. We could borrow from std::filesystem::remove(), return bool and then make -f the default.

file_exists( std::string const& path );

std::vector< std::string >
list_directory(std::string const& path );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docstring: non-recursive, files-only?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-recursive, every entry (i.e. directories and files).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Best to just put this info in the doxygen doc string I guess.

namespace auxiliary
{
bool
path_exists( std::string const& path );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this directory_exists?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it actually checks for a directory. This should be made more explicit.

REQUIRE(path_exists("/home"));
REQUIRE(!path_exists("/nonexistent_folder_in_root_directory"));
#endif
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing end-of-file newline

C0nsultant and others added 4 commits May 28, 2018 21:45
We support either windows or POSIX systems.

Keep the checks of defines local for it.
@ax3l ax3l force-pushed the topic/replace_boost.filesystem branch from c32fa93 to ed84f20 Compare May 29, 2018 11:15
@ax3l
Copy link
Member

ax3l commented May 29, 2018

Nice, FindHDF5.cmake seems to forget to expose it needs to link against zlib. Fun.

@C0nsultant
Copy link
Member Author

C0nsultant commented May 29, 2018

Do not be mistaken:

Unknown compression format zlib. This might mean that compression will not be enabled.

is a message by our own code:

std::cerr << "Unknown compression format " << format
<< ". This might mean that compression will not be enabled."
<< std::endl;

The current failures are probably because mkdir -p is not yet working, but mkdir is (there's only a test for the latter).

@ax3l ax3l force-pushed the topic/replace_boost.filesystem branch from 8bf6353 to 411228e Compare May 29, 2018 12:12
@ax3l
Copy link
Member

ax3l commented May 29, 2018

Ah ok, I thought it's triggered the other way around. Alright, you can pull again and work on it.

@ax3l
Copy link
Member

ax3l commented May 29, 2018

@C0nsultant I think you should be able to traverse your Unix paths for nested creation of dirs like this:

#include <iostream>
#include <sstream>

void iterEm(std::string input)
{
    std::istringstream ss(input);
    std::string token;

    std::string iterPath;
    if( input.find("/") == 0 )
        iterPath += "/";
    while( std::getline( ss, token, '/' ) ) {
        if( token.size() > 0 )
            iterPath += token + "/";
        std::cout << iterPath << std::endl;
    }
}

int main()
{
    iterEm( "/abc/def/ghi" );
    iterEm( "abc/def/ghi" );
    iterEm( "abc/def/ghi/" );

}

output:

/
/abc/
/abc/def/
/abc/def/ghi/

abc/
abc/def/
abc/def/ghi/

abc/
abc/def/
abc/def/ghi/

Recursively delete directories (like `rm -r`).
Recursively create directories (like `mkdir -p`).
Copy link
Member

@ax3l ax3l left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am confused about deletes in cmake dirs ;)

{
std::string del = "..\\CMakeFiles\\" + *dir_entries.begin();
while( !file_exists(del) && directory_exists(del) )
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:-o what are you removing here? xD

dir_entries = list_directory(del);
del += "/" + *dir_entries.begin();
}
if( file_exists(del) )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks scary and probably harmful, e.g. for make install.

@C0nsultant
Copy link
Member Author

C0nsultant commented May 30, 2018

The idea was to find a file to test deletion on realiably. Maybe we could delete some .cpp files instead?

Use CI support script directory rather than CMake build directory
@ax3l
Copy link
Member

ax3l commented May 30, 2018 via email

@ax3l ax3l mentioned this pull request May 30, 2018
@ax3l
Copy link
Member

ax3l commented May 30, 2018

I will push an update on this in the next hour.

Create a simple file and remove it again.
Avoids touching the CMake tree and source tree.

bool success = true;
#ifdef _WIN32
success = CreateDirectory(path.c_str(), NULL);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

recursive?
https://stackoverflow.com/a/1530815/2719194

(or same as the solution below for POSIX)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That or
https://msdn.microsoft.com/en-us/library/bb762130(v=vs.85).aspx

This function creates a file system folder whose fully qualified path is given by pszPath. If one or more of the intermediate folders do not exist, it creates them.
To set security attributes on a new folder, use SHCreateDirectoryEx.

throw std::system_error(std::error_code(errno, std::system_category()));
dirent* entry;
while ((entry = readdir(directory)) != nullptr)
if( strncmp(entry->d_name, ".", 1) && strncmp(entry->d_name, "..", 2) )
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably skips hidden folders starting with a . we could need checks for both strncmp if the strlen is larger than 1 or 2 respectively.

Recursively delete directories (like `rm -r`).
Recursively create directories (like `mkdir -p`).
@ax3l ax3l changed the title [WIP] Replace boost.filesystem Replace boost.filesystem May 31, 2018
auto mk = [](std::string const& p) -> bool { return CreateDirectory(p.c_str(), nullptr); };
#else
char seperator = '/';
auto mk = [](std::string const& p) -> bool { return (0 == mkdir(p.c_str(), 0777));};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would actually make Windows and POSIX behaviour equivalent. Agreed!

auto entries = list_directory(".");
for( auto const& entry : entries )
std::cout << entry << std::endl;
//REQUIRE(file_exists("AuxiliaryTests.exe"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should these be enabled or removed?

should the output above be on or is it a debug leftover?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be enabled, they just failed because I could not figure out the cwd in appveyor.
Also, the above std::cout loop should be removed again.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For appveyor, this should then be

REQUIRE(file_exists("Release\\AuxiliaryTests.exe"));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, depends if it's a Debug or Release build ("Configuration") in multi-config build systems such as VS that is used as Generator. Maybe just do not check for this exe and check for another file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any file whose (relative) path we can reliably determine is fine, really.
Going from appveyor logs, the cwd is C:\projects\openpmd-api\build\bin.
How about

REQUIRE(file_exists("..\\..\\CMakeLists.txt"));

Copy link
Member

@ax3l ax3l May 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this is just by the WORKING_DIRECTORY I add to the add_test calls in CMakeLists.txt. I am surprised it is not bin\Release\ ...

Update: Actually REQUIRE(file_exists("AuxiliaryTests.exe")); should work as is - can you try again?

Checking the CMakeLists.txt this way is not possible, since it depends on the user-chosen location of the build directory. Let me see which file we can use...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Python bindings are built, it appears we could check for

REQUIRE(file_exists(".\\2_read_serial.py"));

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about it, why not just do the same empty file workaround from 0b87334?
Actually, I think we are good with just relying on 0b87334, which does a file_exists() check on a relative path.
This can be removed, after all.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perfect!

@C0nsultant
Copy link
Member Author

Once both of these minor issues are addressed, we should be ready to merge. 🎆

@ax3l
Copy link
Member

ax3l commented May 31, 2018

Yay, nice! 🚀 Do you want to push it or shall I do it?

@C0nsultant
Copy link
Member Author

@ax3l Pull the trigger.

@ax3l ax3l merged commit 12b8abd into openPMD:dev May 31, 2018
First Stable Release automation moved this from In progress to Done May 31, 2018
@ax3l
Copy link
Member

ax3l commented May 31, 2018

We are free, freeee!

@C0nsultant C0nsultant deleted the topic/replace_boost.filesystem branch May 31, 2018 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend internal refactoring third party third party libraries that are shipped and/or linked
Projects
Development

Successfully merging this pull request may close these issues.

None yet

2 participants