Skip to content

Boost filesystem directory_iterator problem on iOS? #50

@mackworth

Description

@mackworth

Hi, I'm having a weird problem, and before I raise it to the boost folks, I was hoping I can get your "Boost on iOS" opinion, as I'm not a boost expert (barely c++ capable).

When I use the boost filesystem::directory_iterator in my iOS program, it just plain doesn't work.

I started by building the current boost library using your script:

./boost.sh -ios -macos --boost-version 1.73.0 --ios-sdk 13.4 --ios-archs "armv7 arm64" --min-ios-version 10.2 --hidden-visibility --universal --boost-libs "date_time filesystem program_options regex system"

directory_iterator wasn't working and sometimes crashed in the project I'm working on, so I created a new Xcode project (attached below) to narrow it down. All I did was:

  • Build a new single-view project in Xcode
  • Rename AppDelegate.m to AppDelegate.mm
  • Add the code (bottom of this post) to didFinishLaunchingWithOptions
  • Add boost headers to Header Search Path
  • Add library directory to Library Search paths
  • Add libboost_filesystem.a to "Link Binary with Libraries" phase
  • Then run the program.

I'm using current Xcode Version 11.4.1 (11E503a) on current MacOS: 10.15.4 (19E287) and current iOS: 13.4.1 (17E262).

Results: the itr->path exists; once for each file, but is always empty, giving error msg: "" does not exist. I point out that the preceding Cocoa access to the same directory works fine. so the file(s) are there, and the app has rights to get to them. As discussed below, sometimes I also get a malloc crash in directory.cpp > dir_itr_close when the for-loop finishes.

I did the same steps on a macOS version (both a command line version in main.mm and a sandboxed app version in applicationDidFinishLaunching; also attached for your interest). No changes to code at all, and both worked fine, either giving me a listing of my real Documents directory, or just showing the dummy file in the sandboxed Documents.

What triggered my investigation, was that I got two warning messages when compiling in my real project (these are the ones from the test project; I compressed the long names to $DerivedData). As discussed below, these only appear when I compile on the simulator with Inline Methods Hidden: NO

Direct access in function 'boost::filesystem::detail::directory_iterator_construct(boost::filesystem::directory_iterator&, boost::filesystem::path const&, unsigned int, boost::system::error_code*)' from file '$DerivedData/boost-ios/build/iOS/libboost_filesystem.a(directory.o)' to global weak symbol 'boost::system::detail::is_generic_value(int)::gen' from file '$DerivedData/Debug-iphonesimulator/testBoost.build/Objects-normal/x86_64/AppDelegate.o' means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.>

Direct access in function 'boost::system::detail::system_error_category::default_error_condition(int) const' from file '$DerivedData/boost-ios/build/iOS//libboost_filesystem.a(directory.o)' to global weak symbol 'boost::system::detail::is_generic_value(int)::gen' from file '$DerivedData//Debug-iphonesimulator/testBoost.build/Objects-normal/x86_64/AppDelegate.o' means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.

So, with that clue... I tried changing Xcode's Hidden options. In the test project, if I set Inline Methods Hidden (matching the compilation), then I get no warnings, empty file names reported and then a malloc crash. If I turn it off, I get the warnings, empty file names, but no crash. The Symbols Hidden by Default option seems to have no effect in either case. I note that the warnings only appear when I'm compiling on the simulator, but the other results are the same.

I then rebuilt the boost library removing the --hidden-visibility option. Absolutely no effect: Inline Methods hidden still gives no warning, no names and malloc crash; Inline Methods hidden off still gives warning, no names, and no malloc crash.

So, any obvious things I've missed, or suggestions for other things to try before escalating to the boost group?

thx
/Hugh

 using namespace std;
namespace fs = boost::filesystem;

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
 //Create a temp file to list
  NSString * objCPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
  fs::path doc_path(objCPath.fileSystemRepresentation);
  fs::ofstream( doc_path / "/dummyFile.txt" );
 // fs::ofstream( doc_path / "/dummyFile2.txt" );
  
  NSLog(@"Directory Contents: %@", [[NSFileManager defaultManager] contentsOfDirectoryAtPath:objCPath error:nil]);

  fs::directory_iterator end_itr;  // default construction yields past-the-end
  for (fs::directory_iterator itr(doc_path); itr != end_itr; ++itr) {
   fs::path path = itr->path();
   //
    if (exists(path))
      if (is_regular_file(path))
        std::cout << path << "; file size is " << file_size(path) << '\n';
      else if (is_directory(path))
        std::cout << path << " is a directory\n";
      else
        std::cout << path << "exists, but is neither a file nor a directory\n";
    else
      cout << path << " does not exist\n";
  }
  cout << "All done";
  return YES;

TestBoost.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions