Skip to content

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

Closed
Neui wants to merge 3 commits into
pauldreik:mainfrom
Neui:add-feature-test-macros
Closed

Define "feature macros" for symlink, make it compilable on cygwin#39
Neui wants to merge 3 commits into
pauldreik:mainfrom
Neui:add-feature-test-macros

Conversation

@Neui
Copy link
Copy Markdown

@Neui Neui commented Nov 7, 2019

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 Neui force-pushed the add-feature-test-macros branch from f52e0ea to 204c0a8 Compare November 8, 2019 16:58
@pauldreik
Copy link
Copy Markdown
Owner

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.

@Neui
Copy link
Copy Markdown
Author

Neui commented Aug 13, 2021

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.

@pauldreik
Copy link
Copy Markdown
Owner

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?

@BartLH
Copy link
Copy Markdown

BartLH commented Aug 14, 2021

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.

Neui added 3 commits August 14, 2021 21:41
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.
It's to prevent redefinition warnings on systems other than cygwin such
as Ubuntu.
It was determined that just defining _POSIX_C_SOURCE is enough to let
symlink() be defined.
@Neui Neui force-pushed the add-feature-test-macros branch from 204c0a8 to 905a40d Compare August 14, 2021 19:43
@Neui
Copy link
Copy Markdown
Author

Neui commented Aug 14, 2021

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.

@pauldreik
Copy link
Copy Markdown
Owner

I added a cygwin job in #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 pauldreik closed this Jun 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants