I'm trying to port our build system from make to CMake, and I encountered a problem that surprisingly not "Googleable"
Our code is C++ 11/14, compiles fine with GCC6.2, the make applies zillion switches when invoking GCC, mostly pedantic warnings. I built a CMake system that compiles (GCC 6.3) most of the code without a problem but some modules failed to build because of the following
flexible array member ‘blahblah’ not at end of ‘struct‘
Aside why it appears in the C++ code. Why did it compile in the make based system? AFAIK, flexible array is not a part of C++ standard. GCC specific extension? What command line switch controls FAM behavior? How do I make it compile as it did in the original make system?
In case someone needs a snippet of compiled code
struct Foo
{
int _10;
double _20;
int a[];
};
struct Bar
{
Foo foo;
double _1;
int _2;
}
To add more context, the cmake file
cmake_minimum_required(VERSION 3.9)
project(foo VERSION ${FOO_VERSION} DESCRIPTION "foo")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_C_STANDARD 99)
add_executable(foo foo.cpp foo_backup.cpp main.cpp)
set_target_properties(foo PROPERTIES VERSION ${PROJECT_VERSION})
target_include_directories(foo PUBLIC ${CMAKE_SOURCE_DIR}/lib/include ${CMAKE_SOURCE_DIR}/lib/include/bar)
How do I make it compile as it did in the original make system
Revert to GCC 6.2. This -pedantic error was introduced for C++ in GCC 6.3.
See compilation with 6.2 and compilation with 6.3
Disabling pedantic compilation will remove the error but entail other relaxations.
Related
I'm using clang 13.0.0 in a CMAKE-based project, CMAKE_CXX_STANDARD is defined as 20. The following code causes a compilation error (no type named 'u8string' in namespace 'std'):
#include <iostream>
#include <string>
int main() {
#ifdef __cpp_char8_t
std::u8string sss = u8"a"; // <---- this branch is picked up
#else
std::string sss = "b"
#endif
return 0;
}
Below is the CMakeLists.txt:
cmake_minimum_required(VERSION 3.20)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
project(clang_test)
add_executable(clang_test main.cpp)
Am I missing something or is it a clang bug? I mean, if std::u8string is not yet there, the macro shouldn't be defined, right? By the way, if you know the way to undefine it somehow with the CMake, please, share your experience. Here the topic starter faces the same problem, I think, but there is no solution proposed yet.
Update: the platform is RHEL 8.4
Update 2: moved the 'project' call below the compiler settings in the CMakeLists.txt
Frank's suggestion was correct - the problem is in that Clang was using an older version of libstdc++ and not libc++;
target_compile_options(clang_test PRIVATE -stdlib=libc++)
fixes the issue for me. Though I don't entirely understand why it doesn't work with libstdc++, if you have any idea, please, share it here - I assume that this is a separate question.
Also, Tsyvarev's point is indeed a very important one, and the compiler should be set before the project call. I've corrected the example in my question.
Update: Finally I understand the reason why it fails: __cpp_char8_t is not sufficient for std::u8string, __cpp_lib_char8_t should be used instead.
Thanks everyone for your help!
The following code builds just fine under cl, but fails under clang-cl:
#define NUDGE_FORCEINLINE __forceinline
NUDGE_FORCEINLINE __m128 operator-(__m128 a) {
return _mm_xor_ps(a, _mm_set1_ps(-0.0f));
}
This is the error message:
..\nudge.cpp(65,26): error: overloaded 'operator-' must have at least one parameter of class or enumeration type
NUDGE_FORCEINLINE __m128 operator-(__m128 a) {
^
The code is from rasmusbarr/nudge, an experiment which seems to be abandoned since 2017.
Setup (CMake/VSCode):
cl with VS Build Tools 2019 v16.8.2
clang-cl with C++ Clang Tools for Windows 10.0.0 (VS Build Tools 2019 v16.8.2)
cmake_minimum_required(VERSION 3.18.0)
project(nudge LANGUAGES C CXX)
add_executable(tests "nudge.cpp" "tests/main.cpp")
target_include_directories(tests PRIVATE ${CMAKE_SOURCE_DIR})
Research:
I came across these two sources (1, 2) that seem to point out that the reason might be clang-cl does not consider __m128 to be a struct type. They fixed it in (1), but it seems that they just disable SSE for some platforms.
Although it was a long shot, I tried compiling with the VS version of immintrin.h and intrin.h but that path led nowhere.
I also noticed that someone else who build this experiment used the c++11 standard so I tried that too by setting set(CMAKE_CXX_STANDARD 11) in cmake. No change.
Question:
How can I modify the code (or change compiler flags) in order to build rasmusbarr/nudge with clang-cl?
Thank you
These days I was fiddling with a project study for a data model with a kind of reflection suitable to my needs.
While I got my first study running with the recent stable version of g++, I failed in Visual Studio 19. Too bad, because the latter is my primary platform…
Effectively, I try to store a pointer to member variable into another static member variable. Thereby, it's really desirable for me to do this inline (to fit into my bigger concept).
I reduced the failing detail to the following MCVE:
struct Field { };
struct Class {
template <typename CLASS>
struct BuiltInInfoT {
Field CLASS::*const pField; // member pointer
};
};
struct Object: Class {
Field field1;
static inline BuiltInInfoT<Object> field1BuiltInfo = { &Object::field1 };
};
int main()
{
Object obj;
}
Puzzled that this seems to work in g++ but not in MSVC, I had a look on Compiler Explorer what other compilers say about this. So, I found that recent clang and even the recent ICC (I never used before) accept this.
Live Demo on Compiler Explorer
I tried the same with an even simpler previous example where I didn't use any templates:
#include <iostream>
struct Test {
struct Info { int Test::*p; };
int a;
static inline Info infoA = { &Test::a };
int b;
static inline Info infoB = { &Test::b };
Test(int a, int b): a(a), b(b) { }
};
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
DEBUG(Test test(123, 456));
DEBUG(std::cout << (test.*(test.infoA.p)) << '\n');
DEBUG(std::cout << (test.*(test.infoB.p)) << '\n');
}
The result is the same: g++, clang, and ICC compile this fine but MSVC complains.
Live Demo on Compiler Explorer
So, now I'm a bit uncertain.
Is it a bug of MSVC that might be worth to be reported? Or am I expecting something I should not rely on?
Disclaimer:
Of course, I googled this topic the last 3 days and found zillions of tutorials about how to use a member pointer – including the answer to SO: What is the meaning of this star (*) symbol in C++? — Pointer to member I've written myself. Maybe, I was missing the essential keyword but I promise I really tried hard.
In case, you're wondering what I'm trying to do…
The actual project study as Live Demo on coliru from which I made my above MCVE.
Update:
After a long discussion, #doug helped me to find out that this seems to be subject of the Visual Studio property settings. With a clean started project, I got all the above mentioned samples running in my local VS 2019. (Before, I used CMake-generated projects as usual.) I will compare the options of two resp. VS projects to find out the significant difference and post an update if I found something…
#doug gave me the hint that he got my code running in VS 2019 without any complaints.
After a long chat, he gave me the hint to test my above samples in a new created VS solution. All I had to do, was to enable C++17 (/std:c++17) and then MSCV compiled all the samples without complaints.
I must admit that I usually use CMake to prepare the VS solutions:
project (OFM)
cmake_minimum_required(VERSION 3.10.0)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
include_directories("${CMAKE_SOURCE_DIR}")
file(GLOB sources *.cc)
file(GLOB headers *.h)
add_executable(testOFM
${sources} ${headers})
So, I had to find the relevant difference in the VS project settings.
Finally, I found it:
the VS created project contains /permissive-
the CMake created project doesn't.
In the projects settings, it is
- C/C++
- Language
- Standards conformance: Yes (/permissive)
The MS online doc.:
/permissive- (Standards conformance)
Specify standards conformance mode to the compiler. Use this option to help you identify and fix conformance issues in your code, to make it both more correct and more portable.
That's exactly what I want: to be standard conform and portable.
Adjusting this option in my CMake generated project, I got it compiled and running as well.
The demos on Compiler Explorer compiled properly (with the sufficient command line arguments):
Live Demo on Compiler Explorer
Live Demo on Compiler Explorer
and even the initial study (where my trouble started from):
Live Demo on Compiler Explorer
What I wonder: When I wrote my CMake script I already used
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
with the exact intention to be standard conform and portable.
So, there seems to be something else I have to setup in CMake.
(The last resort could be a platform-specific setting but I will investigate to find something else if possible.)
Concerning my problem, I found
CMake Issue #17068:MSVC toolset 14.1+: Set /permissive- when CXX_EXTENSIONS==OFF?
After I have fixed my CMake script with a compiler specific option:
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if (MSVC)
add_compile_options(/permissive-)
endif()
and generated my VS solution / projects again the code compiled without any complaints as well.
#Scheff has identified a problem likely to affect others re inline static member initialization. It's particularly problematic as it differently affects compiler explorer c++17 defaults v MSVC IDE c++17 defaults. See his answer and analysis:
Using the default c++ settings (c++14) for MSVC which doesn't allow inline static members.
Change the setting to c++17 or higher. This is the usual cause of inline static initialization on the same line.
However, after chat, it turns out c++17 is being used but the difference is that it's being used with CMake. Apparently there is a difference between CMake and an MSBuild solution/project file. The latter works, the former doesn't. Under investigation and will update with results.
Hi i am working on C++11 related feature , i need to include header file such as
#include <zmqpp/zmqpp.hpp>
in my source code and i wrote some simple g++ script to compile it such as
g++ client.c -o client
i just realized i need to run it with additional argument
g++ -std=gnu++11 client.c .......
in order for me compile successfully.
I am curious what is the default compiler for g++? is it possible for me set
-std=gnu++11 as my default c++ compiler?
Let me know if this duplicated, i was googling around but i don't see any information related to my scenario. Thanks
as stated here, the only way to change the standard version is to rebuild a custom version of g++. If you are using Linux, I recommend having a custom alias in .bashrc, like so:
alias g++11='g++ -std=c++11';
CMake is another common method to do this, simply add this directive to make the default version C++11 :
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
Keep in mind CMake is typically used for projects, so it may not be applicable to your use case.
When I add the flag -flto to my NDK C++ project the linker emits the following error: "Optimization level must be between 0 and 3", even though my optimization level is explicitly set to 3 via -O3.
Does anyone know how to solve this?
The compiler flags are passed via Gradle which, as I understand it, should pass the flags to both the Clang compiler and linker. When I remove the -flto flag everything works fine.
Notes:
I'm using NDK 19.2 (latest version at the time I write this).
I also get the warning "clang++.exe: warning: argument unused during compilation: '-Wa,--noexecstack' [-Wunused-command-line-argument]" which I do not have if I compile without link time optimizations.
Two parts to the answer:
The error is caused by https://github.com/android-ndk/ndk/issues/721. Clang's LTO plugin just doesn't accept -Os or -Oz. This is a bug.
Okay, I might be really stupid, I suppose between 0 and 3 means 1 or 2 :)
It's actually because you can't use the generic cppFlags to set optimization levels. That corresponds to CMAKE_CXX_FLAGS, and you need to set these in CMAKE_CXX_FLAGS_DEBUG and CMAKE_CXX_FLAGS_RELEASE (and/or the C flavors of those). CMake has its own defaults in those variables and the command line is built as ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}, so your -O3 is being overridden by the default.
I also encounter this linking error but I fixed through a different way.
I had cross-compile a library for android with architectures of both arm64 and armv7. It's all OK for arm64 but encounter the linking error for armv7. And I found it can be fixed by commented out the following statements in my CMakeLists.txt:
if (${CMAKE_MAJOR_VERSION} GREATER_EQUAL 3 AND ${CMAKE_MINOR_VERSION} GREATER_EQUAL 9)
cmake_policy(SET CMP0069 NEW)
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
include(CheckIPOSupported)
check_ipo_supported(RESULT ipo_supported OUTPUT ipo_supported_output)
if (ipo_supported)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif ()
endif ()
The above CMake statements are related to the IPO setting and it seems cause the linking error when cross-compiling for android armv7.
I don't know why the IPO should not enabled for android armv7.