rdfind icon indicating copy to clipboard operation
rdfind copied to clipboard

Define "feature macros" for symlink, make it compilable on cygwin

Open Neui opened this issue 6 years ago • 5 comments

Define _XOPEN_SOURCE and _POSIX_C_SOURCE appropriately in order to be able to use functions such as symlink() on cygwin.

Before that it would error while running make about not being able to find a function called symlink. After looking into the header files, I've found it requires at least one of those macros in order to be defined.

The error was:

g++ -std=c++11 -DHAVE_CONFIG_H -I.     -g -O2 -MT Fileinfo.o -MD -MP -MF .deps/Fileinfo.Tpo -c -o Fileinfo.o Fileinfo.cc
Fileinfo.cc: In lambda function:
Fileinfo.cc:280:14: error: ‘symlink’ was not declared in this scope
       return symlink(target.c_str(), filename.c_str());
              ^~~~~~~
Fileinfo.cc:280:14: note: suggested alternative: ‘unlink’
       return symlink(target.c_str(), filename.c_str());
              ^~~~~~~
              unlink

Additionally, man 2 symlink (on Ubuntu 18.04) says, it'll be defined for:

    _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200112L
        || /* Glibc versions <= 2.19: */ _BSD_SOURCE

However, defining _BSD_SOURCE would cause cygwin sys/feature.h to define _DEFAULT_SOURCE, which in turns always redefines _POSIX_C_SOURCE, causing an redefinition warning when the config.h file is processed again. Thus _BSD_SOURCE isn't defined, for now.

This is also my first time modifying autoconfig files. I hope I did everything alright. Note that it just builds and is functional (can find duplicates), but I haven't tried anything advanced yet (like dryrun, actually soft or hard symlinking).

Neui avatar Nov 07 '19 20:11 Neui

Sorry for replying so late.

Is this how those macros are supposed to be used (set by the user)?

Regardless, it may be wise to check for symlink support during configure time so rdfind can compile also without it. That would require some kind of mechanism to inhibit the symlink tests.

For a code change like this, some kind of CI for testing this is needed. Preferably cygwin.

pauldreik avatar Aug 13 '21 08:08 pauldreik

Sorry for replying so late.

I already forgot about this.

Is this how those macros are supposed to be used (set by the user)?

According to the linked man page 7 feature_test_macros, these macros should just simply defined before including the appropriate header, like either on the command line or a simple #define (which seems what I've done). It also says that _POSIX_C_SOURCE is in the POSIX.1 standard, but _BSD_SOURCE is an extension.

On cygwin I get the 3p version of the man page which doesn't say anything about it, but also claims that the cygwin implementation can differ.

With my initial comment above, it seems that defining _POSIX_C_SOURCE should be enough in most cases, except maybe very legacy systems(/BSDs).

Regardless, it may be wise to check for symlink support during configure time so rdfind can compile also without it. That would require some kind of mechanism to inhibit the symlink tests.

I believe autotools has such functionality available, but we still need to define those macros above so in case it is available it can be used.

For a code change like this, some kind of CI for testing this is needed. Preferably cygwin.

I agree, but I haven't looked on how you would do that yet. AFAIK appveyor can run windows MSVC, but not sure if we can also use cygwin on there.

Neui avatar Aug 13 '21 18:08 Neui

Thanks for providing information on how to use the macros!

I removed appveyor and moved what it ran into github actions instead. Do you think something https://github.com/egor-tensin/setup-cygwin could be used?

pauldreik avatar Aug 14 '21 08:08 pauldreik

This is a continuation of #56 as well, but fits better in this thread.

I looked a bit more into the specific definitions that are needed to enable symlink. Symlink is defined in sys/unistd.h. In the version of that header that is used by MSYS and Cygwin the function definition is guarded by #if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 4 Note that this is a bit different than the definition that @Neui found on Ubuntu 18.04.

For our purposes the most important one is __POSIX_VISIBLE . This is defined in sys/features.h:

#if (_POSIX_C_SOURCE - 0) >= 200809L
#define	__POSIX_VISIBLE		200809
#elif (_POSIX_C_SOURCE - 0) >= 200112L
#define	__POSIX_VISIBLE		200112
#elif (_POSIX_C_SOURCE - 0) >= 199506L
#define	__POSIX_VISIBLE		199506
#elif (_POSIX_C_SOURCE - 0) >= 199309L
#define	__POSIX_VISIBLE		199309
#elif (_POSIX_C_SOURCE - 0) >= 2 || defined(_XOPEN_SOURCE)
#define	__POSIX_VISIBLE		199209
#elif defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE)
#define	__POSIX_VISIBLE		199009
#else
#define	__POSIX_VISIBLE		0
#endif

You can see here that this means we should set _POSIX_C_SOURCE to 200112. Defining _XOPEN_SOURCE , _BSD_SOURCE and/or _DEFAULT_SOURCE should not be needed, and in fact enables more extensions than are necessary, as also explained on https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html. Since @pauldreik indicated he's not a fan of extensions, I believe we shouldn't enable more of them than strictly needed.

Sidenote, my earlier solution of just enabling all extensions is equivalent to defining _GNU_SOURCE and undefining __STRICT_ANSI__, which in turn leads to (among others) #define _POSIX_C_SOURCE 200809L, which is of course larger than 200112L.

I tested with ./configure CXXFLAGS="-std=c++11 -D_POSIX_C_SOURCE=200112" and that works fine.

BartLH avatar Aug 14 '21 14:08 BartLH

I removed appveyor and moved what it ran into github actions instead. Do you think something egor-tensin/setup-cygwin could be used?

No idea, I've never used GitHub Actions, but the repository looks like it could work.

Because of BartLH I've now added a commit to just keep the _POSIX_C_SOURCE definition (in addition to rebase on top of the current main branch). It compiles on Cygwin and on Ubuntu 20.04. I'm not doing the symlink detection in this specific PR to keep things simple here.

Neui avatar Aug 14 '21 19:08 Neui

I added a cygwin job in https://github.com/pauldreik/rdfind/pull/136 . It did not require any changes. Help wanted to test if the cygwin executable works, and if it would be possible to execute the tests.

Since no changes were needed to make it compile, I think this PR should be closed. Thanks for the work!

pauldreik avatar Jun 17 '23 13:06 pauldreik