robotology / yarp

YARP - Yet Another Robot Platform
http://www.yarp.it
Other
525 stars 195 forks source link

YARP_CLEAN_API flag is currently broken #978

Closed drdanz closed 7 years ago

drdanz commented 7 years ago

If YARP_CLEAN_API is enabled and YARP_COMPILE_TESTS is disabled, YARP build currently fails with this error:

[ 25%] Building CXX object src/libYARP_OS/CMakeFiles/YARP_OS.dir/src/Module.cpp.o
In file included from <yarp>/src/libYARP_OS/include/yarp/os/impl/Logger.h:12:0,
                 from <yarp>/src/libYARP_OS/src/Module.cpp:13:
<yarp>/build/generated_include/yarp/conf/api.h:60:36: error: expected identifier before ‘__attribute__’
 #    define YARP_HELPER_DLL_EXPORT __attribute__ ((visibility("default")))
                                    ^
<yarp>/build/generated_include/yarp/conf/api.h:75:23: note: in expansion of macro ‘YARP_HELPER_DLL_EXPORT’
 #  define YARP_EXPORT YARP_HELPER_DLL_EXPORT
                       ^~~~~~~~~~~~~~~~~~~~~~
<yarp>/src/libYARP_OS/include/yarp/os/api.h:13:25: note: in expansion of macro ‘YARP_EXPORT’
 #    define YARP_OS_API YARP_EXPORT
                         ^~~~~~~~~~~
<yarp>/src/libYARP_OS/include/yarp/os/api.h:23:52: note: in expansion of macro ‘YARP_OS_API’
 #    define YARP_OS_DEPRECATED_API YARP_DEPRECATED YARP_OS_API
                                                    ^~~~~~~~~~~
<yarp>/src/libYARP_OS/include/yarp/os/Module.h:45:7: note: in expansion of macro ‘YARP_OS_DEPRECATED_API’
 class YARP_OS_DEPRECATED_API yarp::os::Module : public IConfig {
       ^~~~~~~~~~~~~~~~~~~~~~
In file included from <yarp>/src/libYARP_OS/src/Module.cpp:15:0:
<yarp>/src/libYARP_OS/include/yarp/os/Module.h:45:47: error: expected initializer before ‘:’ token
 class YARP_OS_DEPRECATED_API yarp::os::Module : public IConfig {
                                               ^
src/libYARP_OS/CMakeFiles/YARP_OS.dir/build.make:3254: recipe for target 'src/libYARP_OS/CMakeFiles/YARP_OS.dir/src/Module.cpp.o' failed
make[2]: *** [src/libYARP_OS/CMakeFiles/YARP_OS.dir/src/Module.cpp.o] Error 1
CMakeFiles/Makefile2:360: recipe for target 'src/libYARP_OS/CMakeFiles/YARP_OS.dir/all' failed
make[1]: *** [src/libYARP_OS/CMakeFiles/YARP_OS.dir/all] Error 2
Makefile:149: recipe for target 'all' failed
make: *** [all] Error 2

This is not currently tested on travis, and it is normally not used because tests cannot currently compile with that flag enabled, therefore if you enable tests (on by default) this flag is not used even if you enable it manually.

We should fix it, enable the build on travis and, at some point, fix the tests so that you can compile them with this flag enabled

drdanz commented 7 years ago

After some more testing, I believe this is an issue with recent gcc versions (tested with 6.2.0). I don't see this with clang 3.8.1, and I cannot reproduce this on travis

drdanz commented 7 years ago

Also it does not fail C++11 is enabled

drdanz commented 7 years ago

Adding -std=c++98 to the build flags fixes this issue. The problem comes from g++ defining (even if c++11/14 is not enabled) __cplusplus=201402L and therefore the [[deprecated]] construct is used but it is not recognized by gcc itself.

I'd say this is a bug in the compiler.

traversaro commented 7 years ago

Gcc 6 switched the default c++ standard used to C++14 (https://gcc.gnu.org/gcc-6/changes.html) so the __cplusplus value make sense, the strange thing is that is not recognizing [[deprecated]].

drdanz commented 7 years ago

The following code builds with -std=c++98 and -std=c++11 but not with -std=c++14:

#if defined(__clang__)
#  if ((__clang_major__ * 100) + __clang_minor__) >= 304 && __cplusplus > 201103L
#    define YARP_COMPILER_CXX_ATTRIBUTE_DEPRECATED 1
#  else
#    define YARP_COMPILER_CXX_ATTRIBUTE_DEPRECATED 0
#  endif
#elif defined(__GNUC__)
#  if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L
#    define YARP_COMPILER_CXX_ATTRIBUTE_DEPRECATED 1
#  else
#    define YARP_COMPILER_CXX_ATTRIBUTE_DEPRECATED 0
#  endif
#endif

#  ifndef YARP_DEPRECATED
#    if YARP_COMPILER_CXX_ATTRIBUTE_DEPRECATED
#      define YARP_DEPRECATED [[deprecated]]
#      define YARP_DEPRECATED_MSG(MSG) [[deprecated(MSG)]]
#    elif YARP_COMPILER_IS_GNU || YARP_COMPILER_IS_Clang
#      define YARP_DEPRECATED __attribute__((__deprecated__))
#      define YARP_DEPRECATED_MSG(MSG) __attribute__((__deprecated__(MSG)))
#    elif YARP_COMPILER_IS_MSVC
#      define YARP_DEPRECATED __declspec(deprecated)
#      define YARP_DEPRECATED_MSG(MSG) __declspec(deprecated(MSG))
#    else
#      define YARP_DEPRECATED
#      define YARP_DEPRECATED_MSG(MSG)
#    endif
#  endif

class __attribute__ ((visibility ("default"))) YARP_DEPRECATED foo {};
int main(){}

This also fails:

class YARP_DEPRECATED __attribute__ ((visibility ("default"))) foo {};

Both these work:

class YARP_DEPRECATED foo {};
class __attribute__ ((visibility ("default"))) foo {};

So it is the combination of the attributes that causes issues.

Clang does not have problems building this with -std=c++14

drdanz commented 7 years ago

using [[gnu::visibility("default")]] instead of __attribute__ ((visibility ("default"))) seems to solve the problem

drdanz commented 7 years ago

Unfortunately [[gnu::visibility("default")]] solves this issues for classes, but not for functions that ignore c++11 style attributes printing a warning: attribute ignored [-Wattributes] warning and leaving out the function from the libraries.