Git Product home page Git Product logo

platformfolders's Introduction

PlatformFolders Build Status AppVeyor license Join the chat at https://gitter.im/PlatformFolders/Lobby Codacy Badge

A C++ library to look for directories like My Documents, ~/.config, %APPDATA%, etc. so that you do not need to write platform-specific code

Source codeLatest releaseDoxygen documentation

Rationale

There are a lot of platform abstraction libraries available. You can get graphics abstraction libraries, GUI abstraction libraries and file abstraction libraries.

But folder abstraction seems to be more difficult. My problem was that the code that found the place to save data was platform dependent. This cluttered my code and often I would not discover that it did not compile until moving it to the different platforms.

I have written a bit more about it here.

There are some alternatives that you might consider instead:

Both are properly more mature than this library. However they are both parts of large frameworks and using them with libraries outside the framework may not be that simple.

Operating System Support

Windows

For Windows, the current version fetches the folders using SHGetKnownFolderPath. This requires Vista or newer.

Linux

This library uses the XDG user-dirs.

It should work on any Unix system that has the following headers available: pwd.h, unistd.h, and sys/types.h

macOS

Version 4.0.0 and forward uses hardcoded values for the directories on Mac OS X. Unlike the other operating systems the folders cannot be moved on a Mac and the translation is done in the UI. The versions 2.X and 3.X uses the deprecated FSFindFolder, which requires the CoreServices framework during linking. Version 1.X simple used the XDG specification.

Usage

This project should be compatible with things like Cmake's ExternalProject_Add if you wish to use it in your project.

You can also follow the build step below to install at a system level, and use Cmake's find_package.

# Specifying a version is optional -- note it follows Semver
find_package(platform_folders 3.1.0 REQUIRED)
# Which imports the linkable library "sago::platform_folders"
# Use it like so...
target_link_libraries(EXEORLIBNAME PRIVATE sago::platform_folders)

Alternatively, you can just copy the sago folder into your program and manually link everything. If you use the last option and are using a library version from before 4.0.0: Remember to link to the CoreServices lib when compiling on Mac. This typically means passing "-framework CoreServices" during the linking phase.

Note that if you build in-tree, you can link against the Cmake alias sago::platform_folders just like if you had used find_package.

Building

Notes:

  • Until 4.0.0 macOS required the CoreServices framework during linking.
  • If you don't want to install, remove the --target install command.

Linux/macOS:

mkdir -p build && cd build
cmake -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Release ..
sudo cmake --build . --target install

Windows:

mkdir build && cd build
cmake -DBUILD_TESTING=OFF ..
runas /user:Administrator "cmake --build . --config Release --target install"

Example Usage

This sample program gets all folders from the system:

#include <sago/platform_folders.h>
#include <iostream>
#include <string>

int main()
{
	std::cout << "Config: " << sago::getConfigHome() << "\n";
	std::cout << "Data: " << sago::getDataHome() << "\n";
	std::cout << "State: " << sago::getStateDir() << "\n";
	std::cout << "Cache: " << sago::getCacheDir() << "\n";
	std::cout << "Documents: " << sago::getDocumentsFolder() << "\n";
	std::cout << "Desktop: " << sago::getDesktopFolder() << "\n";
	std::cout << "Pictures: " << sago::getPicturesFolder() << "\n";
	std::cout << "Music: " << sago::getMusicFolder() << "\n";
	std::cout << "Video: " << sago::getVideoFolder() << "\n";
	std::cout << "Download: " << sago::getDownloadFolder() << "\n";
	std::cout << "Save Games 1: " << sago::getSaveGamesFolder1() << "\n";
	std::cout << "Save Games 2: " << sago::getSaveGamesFolder2() << "\n";
	return 0;
}

Example Output

On Linux

Config: /home/poul/.config
Data: /home/poul/.local/share
State: /home/poul/.local/state
Cache: /home/poul/.cache
Documents: /home/poul/Dokumenter
Desktop: /home/poul/Skrivebord
Pictures: /home/poul/Billeder
Music: /home/poul/Musik
Video: /home/poul/Videoklip
Download: /home/poul/Hentede filer
Save Games 1: /home/poul/.local/share
Save Games 2: /home/poul/.local/share

On Windows

Config: C:\users\poul\Application Data
Data: C:\users\poul\Application Data
State: C:\users\poul\Local Settings\Application Data
Cache: C:\users\poul\Local Settings\Application Data
Documents: C:\users\poul\Mine dokumenter
Desktop: C:\users\poul\Skrivebord
Pictures: C:\users\poul\Mine Billeder
Music: C:\users\poul\Min Musik
Video: C:\users\poul\Mine Film
Download: C:\users\poul\Downloads
Save Games 1: C:\users\poul\Mine dokumenter\My Games
Save Games 2: C:\users\poul\Saved Games

On macOS

Config: /Users/poul/Library/Application Support
Data: /Users/poul/Library/Application Support
State: /Users/poul/Library/Application Support
Cache: /Users/poul/Library/Caches
Documents: /Users/poul/Documents
Desktop: /Users/poul/Desktop
Pictures: /Users/poul/Pictures
Music: /Users/poul/Music
Video: /Users/poul/Movies
Download: /Users/poul/Downloads
Save Games 1: /Users/poul/Library/Application Support
Save Games 2: /Users/poul/Library/Application Support

Compiler Compatibility

Versions up to 3.X.X should compile with any C++98 compiler.
Versions from 4.0.0 and up require a C++11 compatible compiler.

The aim is to always support the default C++ compiler on the oldest supported version of Ubuntu. This is a very basic library and it is not supposed to force you to upgrade.

Encoding

From version 3.0, Windows always encodes to UTF-8, and this will be the default on almost any other system. Before version 3.0, Windows was encoded in ANSI. Although the user may use any characters they want, I recommend that the program should have only ASCII characters in the source code itself.

Licence

Provided under the MIT license for the same reason XDG is licensed under it. So that you can quickly copy-paste the methods you need or just include the "sago"-folder.

platformfolders's People

Contributors

domenn avatar firas-assaad avatar kogia-sima avatar olivierldff avatar sago007 avatar sum01 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

platformfolders's Issues

Drop Core framwork for OS X

At the moment PlatformFolders uses CoreServices to find the relevant folders on OS X. However that may be overkill.

Unlike other operating system (like Linux and Windows) OS X does not allow the common directories to be moved or renamed. Moving a folder to another drive involves symlinking it and translations are done fully in the UI.

The "Public" folder is already hardcoded as it is not supported by FSFindFolder. I wonder if I should do the same with the rest. Can anyone see anything bad in this approach?

Reference:
https://apple.stackexchange.com/questions/145476/move-documents-folder-to-different-drive
https://developer.apple.com/library/archive/documentation/General/Conceptual/MOSXAppProgrammingGuide/AppRuntime/AppRuntime.html
https://apple.stackexchange.com/questions/24159/how-do-i-rename-the-downloads-folder-in-lion/24258#24258

npm install fails

Hi, I just tried npm i platform-folders but the build fails. This is the error I get:

C:\Users\federico.ceriani\Documents\Projects\tester-setup\node_modules\platform-folders>if not defined npm_config_node_gyp (node "C:\Program Files\nodejs\node_modules\npm\node_modules\npm-lifecycle\node-gyp-bin\\..\..\node_modules\node-gyp\bin\node-gyp.js" rebuild )  else (node "C:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js" rebuild ) 
gyp ERR! configure error
gyp ERR! stack Error: Command failed: C:\Users\federico.ceriani\AppData\Local\Programs\Python\Python38-32\python.EXE -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack   File "<string>", line 1
gyp ERR! stack     import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack                       ^
gyp ERR! stack SyntaxError: invalid syntax
gyp ERR! stack
gyp ERR! stack     at ChildProcess.exithandler (child_process.js:294:12)
gyp ERR! stack     at ChildProcess.emit (events.js:189:13)
gyp ERR! stack     at maybeClose (internal/child_process.js:970:16)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:259:5)
gyp ERR! System Windows_NT 10.0.18362
gyp ERR! command "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild"
gyp ERR! cwd C:\Users\federico.ceriani\Documents\Projects\tester-setup\node_modules\platform-folders
gyp ERR! node -v v10.15.3
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok

I suspect this has something to do with python? Not sure.

Consider header-only library?

Hello,

I found this library at a perfect moment - just when I started having bugs on Apple devices due to platform-specific folders. I'm enjoying it so far, but had one question about it: are there any plans to convert it to a header-only library, that way I don't have to mark the .cpp file as a source?

Thanks!

How to deal with this library in WebAssembly

Hi there, thank you for this amazing library. I used it everywhere in the past years.
Now, I am porting my desktop application framework to also run in browsers using Emscripten/WebAssembly.
The idea is to streamline app development and to be able to create apps that out of the box run on desktop, and in the browser.

Now, the library compiles fine in Emscripten, no issues there. However, if I run the program, I get an exception "Unable to get passwd struct". I see this is normal behavior, as it seems to call a system function, that is presumably doomed to fail in a web environment.
This is to be expected.

Now, you seem to have more knowledge than me about filesystems and file locations in general. Have you ever thought about WebAssembly or how your library would relate to browser environments?
I could just bypass the library and hard-code file locations, but do you know of any standards of file locations in a browser? Or virtual file systems?

TLDR there is nothing wrong with the library but I am wondering if you ever thought about it and how you would handle it.

Add Linux XDG State directory

Recently (not sure exactly when, but it's in version 0.8 of the spec), the XDG Base Directory specification added a new directory for state information such as log files and session data. This can be used as a replacement for game save directories mentioned here.

As per the specification:

The $XDG_STATE_HOME contains state data that should persist between (application) restarts, but that is not important or portable enough to the user that it should be stored in $XDG_DATA_HOME. It may contain:

  • actions history (logs, history, recently used files, …)

  • current state of the application that can be reused on a restart (view, layout, open files, undo history, …)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.