I would like to use std::experimental::filesystem
in my code, this requires me to compile using -lstdc++fs
with GCC and -lc++experimental
with Clang. At the moment I have a makefile
and makefile.clang
reflecting the difference in compilation, alternatively I've thought about using a clang build target so I can run build clang
.
Is there some canonical way to set compiler-specific flags in a makefile?
For example, even though Clang implements atomic intrinsics which correspond exactly with C11 atomics, it also implements GCC's __sync_* intrinsics for compatibility with GCC and libstdc++. Clang also maintains ABI compatibility with GCC-generated object code.
Clang is designed as an API from its inception, allowing it to be reused by source analysis tools, refactoring, IDEs (etc) as well as for code generation. GCC is built as a monolithic static compiler, which makes it extremely difficult to use as an API and integrate into other tools.
Clang reduces the single-thread compilation time by 5% to 10% compared with GCC. Therefore, Clang offers more advantages for the construction of large projects.
As the user "Some programmer dude" mentioned, there are conditionals in GNU make. You could easily check for the compiler version this way:
CXXFLAGS = -Og -Wall -Wextra
GCC_CXXFLAGS = -DMESSAGE='"Compiled with GCC"'
CLANG_CXXFLAGS = -DMESSAGE='"Compiled with Clang"'
UNKNOWN_CXXFLAGS = -DMESSAGE='"Compiled with an unknown compiler"'
ifeq ($(CXX),g++)
CXXFLAGS += $(GCC_CXXFLAGS)
else ifeq ($(CXX),clang)
CXXFLAGS += $(CLANG_CXXFLAGS)
else
CXXFLAGS += $(UNKNOWN_CXXFLAGS)
endif
Given the following source file test.cpp
you can compile it with make CXX=g++ test
or make CXX=clang test
and it should pass the appropriate flags to each compiler.
#include <iostream>
int main() {
std::cout << "Hello World " << MESSAGE << std::endl;
return 0;
}
You can use CMake to achieve that. It is a better to use if you want to have portable code.
CMake allows to generate Makefile that is appropriate for your system(e.g. your system default compiler). CMake has a lot of features that can be very useful to check actual system configuration.
In this answer, you have example how do that: In cmake, how can I test if the compiler is Clang?
A reliable check is to use the CMAKE__COMPILER_ID variables. E.g., to check the C++ compiler:
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # using Clang elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # using GCC elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") # using Intel C++ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # using Visual Studio C++ endif()
If you still want to use Makefile you should check this answer: https://stackoverflow.com/a/2826178/7042963
In order to handle versioned compilers, like you mentioned in the comment to the accepted answer, you need to use $(findstring find,in)
as such:
# Detect if CXX is g++ or clang++, in this order.
ifeq '' '$(findstring clang++,$(CXX))'
LDLIBS = -lstdc++fs
else
LDLIBS = -lc++experimental
endif
The caveat here is that you cannot use $(findstring g++,$(CXX))
since it'll match clang++
unintentionally.
A more in-depth alternative to handle things more precisely would be:
# Detect if CXX is clang++ or g++, in this order.
ifneq '' '$(findstring clang++,$(CXX))'
LDLIBS = -lc++experimental
else ifneq '' '$(findstring g++,$(CXX))'
LDLIBS = -lstdc++fs
endif
This approach parses the compiler's version string looking for clang
. If it doesn't find clang
then it looks for g++
in order to resolve an issue with macOS, where g++
is aliased to clang
.
# Set compiler-specific flags
GCC_CXXFLAGS = -DMESSAGE='"Compiled with GCC"'
CLANG_CXXFLAGS = -DMESSAGE='"Compiled with Clang"'
UNKNOWN_CXXFLAGS = -DMESSAGE='"Compiled with an unknown compiler"'
# Detect if CXX is clang++ or g++, in this order.
COMPILER_VERSION := $(shell $(CXX) --version)
ifneq '' '$(findstring clang,$(COMPILER_VERSION))'
CFLAGS += $(CLANG_CXXFLAGS)
else ifneq '' '$(findstring g++,$(COMPILER_VERSION))'
CFLAGS += $(GCC_CXXFLAGS)
else
$(warning Unknown compiler)
CFLAGS += $(UNKNOWN_CXXFLAGS)
endif
Credit to @bit2shift's answer, which inspired this one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With