Reputation: 965
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?
Upvotes: 15
Views: 26343
Reputation: 9728
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.
Upvotes: 4
Reputation: 676
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
Upvotes: 4
Reputation: 3707
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;
}
Upvotes: 17