Add pgo builds with GCC and LLVM to Makefile

This commit is contained in:
Christian Speckner 2019-03-03 16:40:07 +01:00
parent 8856789438
commit 24305371c7
5 changed files with 158 additions and 30 deletions

151
Makefile
View File

@ -49,10 +49,17 @@ ifdef CXXFLAGS
else else
CXXFLAGS:= -O2 -x c++ CXXFLAGS:= -O2 -x c++
endif endif
CXXFLAGS+= -Wall -Wextra -Wno-unused-parameter -Wno-ignored-qualifiers CXXFLAGS+= -Wall -Wextra -Wno-unused-parameter -Wno-ignored-qualifiers
ifdef HAVE_GCC ifdef HAVE_GCC
CXXFLAGS+= -Wno-multichar -Wunused -fno-rtti -Woverloaded-virtual -Wnon-virtual-dtor -std=c++14 CXXFLAGS+= -Wno-multichar -Wunused -fno-rtti -Woverloaded-virtual -Wnon-virtual-dtor -std=c++14
endif endif
ifdef HAVE_CLANG
CXXFLAGS+= -Wno-multichar -Wunused -fno-rtti -Woverloaded-virtual -Wnon-virtual-dtor -std=c++14
endif
ifdef CLANG_WARNINGS ifdef CLANG_WARNINGS
CXXFLAGS+= -Weverything -Wno-c++17-extensions -Wno-c++98-compat -Wno-c++98-compat-pedantic \ CXXFLAGS+= -Weverything -Wno-c++17-extensions -Wno-c++98-compat -Wno-c++98-compat-pedantic \
-Wno-double-promotion -Wno-switch-enum -Wno-conversion -Wno-covered-switch-default \ -Wno-double-promotion -Wno-switch-enum -Wno-conversion -Wno-covered-switch-default \
@ -62,23 +69,60 @@ ifdef CLANG_WARNINGS
endif endif
ifdef PROFILE ifdef PROFILE
PROF:= -g -pg -fprofile-arcs -ftest-coverage PROF:= -pg -fprofile-arcs -ftest-coverage
CXXFLAGS+= $(PROF) CXXFLAGS+= $(PROF)
endif
ifdef DEBUG
CXXFLAGS += -g
else else
ifdef HAVE_GCC ifdef HAVE_GCC
CXXFLAGS+= -fomit-frame-pointer CXXFLAGS+= -fomit-frame-pointer
endif endif
endif
ifdef HAVE_CLANG
CXXFLAGS+= -fomit-frame-pointer
endif
endif
####################################################################### #######################################################################
# Misc stuff - you should never have to edit this # # Misc stuff - you should never have to edit this #
####################################################################### #######################################################################
EXECUTABLE := stella$(EXEEXT) EXECUTABLE := stella$(EXEEXT)
EXECUTABLE_PROFILE_GENERATE := stella-pgo-generate$(EXEEXT)
EXECUTABLE_PROFILE_USE := stella-pgo$(EXEEXT)
PROFILE_DIR = $(CURDIR)/profile
PROFILE_OUT = $(PROFILE_DIR)/out
PROFILE_STAMP = profile.stamp
CXXFLAGS_PROFILE_GENERATE = $(CXXFLAGS)
CXXFLAGS_PROFILE_USE = $(CXXFLAGS)
LDFLAGS_PROFILE_GENERATE = $(LDFLAGS)
STELLA_PROFILE_GENERATE = $(BINARY_LOADER) ./$(EXECUTABLE_PROFILE_GENERATE) -profile \
$(PROFILE_DIR)/128.bin:10 \
$(PROFILE_DIR)/catharsis_theory.bin:60
ifdef HAVE_CLANG
CXXFLAGS_PROFILE_GENERATE += -fprofile-generate=$(PROFILE_OUT)
CXXFLAGS_PROFILE_USE += -fprofile-use=$(PROFILE_OUT)
LDFLAGS_PROFILE_GENERATE += -fprofile-generate
STELLA_PROFILE_GENERATE := \
LLVM_PROFILE_FILE="$(PROFILE_OUT)/default.profraw" $(STELLA_PROFILE_GENERATE) && \
$(LLVM_PROFDATA) merge -o $(PROFILE_OUT)/default.profdata $(PROFILE_OUT)/default.profraw
endif
ifdef HAVE_GCC
CXXFLAGS_PROFILE_GENERATE += -fprofile-generate -fprofile-dir=$(PROFILE_OUT)
CXXFLAGS_PROFILE_USE += -fprofile-use -fprofile-dir=$(PROFILE_OUT)
LDFLAGS_PROFILE_GENERATE += -fprofile-generate
LDFLAGS_PROFILE_USE += -fprofile-generate
endif
all: $(EXECUTABLE) all: $(EXECUTABLE)
pgo: $(EXECUTABLE_PROFILE_USE)
###################################################################### ######################################################################
# Various minor settings # Various minor settings
@ -119,57 +163,118 @@ CPPFLAGS:= $(DEFINES) $(INCLUDES)
DEPDIRS = $(addsuffix /$(DEPDIR),$(MODULE_DIRS)) DEPDIRS = $(addsuffix /$(DEPDIR),$(MODULE_DIRS))
DEPFILES = DEPFILES =
OBJS_PROFILE_GENERATE=$(OBJS:.o=.pgen.o)
OBJS_PROFILE_USE=$(OBJS:.o=.pgo.o)
# The build rule for the Stella executable # The build rule for the Stella executable
$(EXECUTABLE): $(OBJS) $(EXECUTABLE): $(OBJS)
$(LD) $(LDFLAGS) $(PRE_OBJS_FLAGS) $+ $(POST_OBJS_FLAGS) $(LIBS) $(PROF) -o $@ $(LD) $(LDFLAGS) $(PRE_OBJS_FLAGS) $+ $(POST_OBJS_FLAGS) $(LIBS) $(PROF) -o $@
$(EXECUTABLE_PROFILE_GENERATE): $(OBJS_PROFILE_GENERATE)
$(LD) $(LDFLAGS_PROFILE_GENERATE) $(PRE_OBJS_FLAGS) $+ $(POST_OBJS_FLAGS) $(LIBS) $(PROF) -o $@
$(EXECUTABLE_PROFILE_USE): $(OBJS_PROFILE_USE)
$(LD) $(LDFLAGS_PROFILE_USE) $(PRE_OBJS_FLAGS) $+ $(POST_OBJS_FLAGS) $(LIBS) $(PROF) -o $@
distclean: clean distclean: clean
$(RM_REC) $(DEPDIRS) $(RM_REC) $(DEPDIRS)
$(RM) build.rules config.h config.mak config.log $(RM) build.rules config.h config.mak config.log
clean: clean:
$(RM) $(OBJS) $(EXECUTABLE) -$(RM) -fr \
$(OBJS) $(OBJS_PROFILE_GENERATE) $(OBJS_PROFILE_USE) \
$(EXECUTABLE) $(EXECUTABLE_PROFILE_GENERATE) $(EXECUTABLE_PROFILE_USE) \
$(PROFILE_OUT) $(PROFILE_STAMP)
.PHONY: all clean dist distclean .PHONY: all clean dist distclean
.SUFFIXES: .cxx .SUFFIXES: .cxx
define create_depdir
$(MKDIR) $(*D)/$(DEPDIR)
endef
define merge_dep
$(ECHO) "$(*D)/" > $(*D)/$(DEPDIR)/$(*F).d
$(CAT) "$(*D)/$(DEPDIR)/$(*F).d2" >> "$(*D)/$(DEPDIR)/$(*F).d"
$(RM) "$(*D)/$(DEPDIR)/$(*F).d2"
endef
ifndef CXX_UPDATE_DEP_FLAG ifndef CXX_UPDATE_DEP_FLAG
# If you use GCC, disable the above and enable this for intelligent # If you use GCC, disable the above and enable this for intelligent
# dependency tracking. # dependency tracking.
CXX_UPDATE_DEP_FLAG = -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d2" CXX_UPDATE_DEP_FLAG = -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d2"
.cxx.o:
$(MKDIR) $(*D)/$(DEPDIR)
$(CXX) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
$(ECHO) "$(*D)/" > $(*D)/$(DEPDIR)/$(*F).d
$(CAT) "$(*D)/$(DEPDIR)/$(*F).d2" >> "$(*D)/$(DEPDIR)/$(*F).d"
$(RM) "$(*D)/$(DEPDIR)/$(*F).d2"
.c.o: %.o: %.cxx
$(MKDIR) $(*D)/$(DEPDIR) $(create_depdir)
$(CC) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o $(CXX) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $@
$(ECHO) "$(*D)/" > $(*D)/$(DEPDIR)/$(*F).d $(merge_dep)
$(CAT) "$(*D)/$(DEPDIR)/$(*F).d2" >> "$(*D)/$(DEPDIR)/$(*F).d"
$(RM) "$(*D)/$(DEPDIR)/$(*F).d2" %.o: %.c
$(create_depdir)
$(CC) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $@
$(merge_dep)
%.pgen.o: %.cxx
$(create_depdir)
$(CXX) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS_PROFILE_GENERATE) $(CPPFLAGS) -c $(<) -o $@
$(merge_dep)
%.pgen.o: %.cxx
$(create_depdir)
$(CC) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS_PROFILE_GENERATE) $(CPPFLAGS) -c $(<) -o $@
$(merge_dep)
%.pgo.o: %.cxx $(PROFILE_STAMP)
$(create_depdir)
$(CXX) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS_PROFILE_USE) $(CPPFLAGS) -c $(<) -o $@
$(merge_dep)
%.pgo.o: %.cxx $(PROFILE_STAMP)
$(create_depdir)
$(CC) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS_PROFILE_USE) $(CPPFLAGS) -c $(<) -o $@
$(merge_dep)
else else
# If you even have GCC 3.x, you can use this build rule, which is safer; the above # If you even have GCC 3.x, you can use this build rule, which is safer; the above
# rule can get you into a bad state if you Ctrl-C at the wrong moment. # rule can get you into a bad state if you Ctrl-C at the wrong moment.
# Also, with this GCC inserts additional dummy rules for the involved headers, # Also, with this GCC inserts additional dummy rules for the involved headers,
# which ensures a smooth compilation even if said headers become obsolete. # which ensures a smooth compilation even if said headers become obsolete.
.cxx.o: %.o: %.cxx
$(MKDIR) $(*D)/$(DEPDIR) $(create_depdir)
$(CXX) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o $(CXX) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $@
%.o: %.c
$(create_depdir)
$(CC) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $@
%.pgen.o: %.cxx
$(create_depdir)
$(CXX) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS_PROFILE_GENERATE) $(CPPFLAGS) -c $(<) -o $@
%.pgen.o: %.c
$(create_depdir)
$(CC) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS_PROFILE_GENERATE) $(CPPFLAGS) -c $(<) -o $@
%.pgo.o: %.cxx $(PROFILE_STAMP)
$(create_depdir)
$(CXX) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS_PROFILE_USE) $(CPPFLAGS) -c $(<) -o $@
%.pgo.o: %.c $(PROFILE_STAMP)
$(create_depdir)
$(CC) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS_PROFILE_USE) $(CPPFLAGS) -c $(<) -o $@
.c.o:
$(MKDIR) $(*D)/$(DEPDIR)
$(CC) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
endif endif
# Include the dependency tracking files. We add /dev/null at the end # Include the dependency tracking files. We add /dev/null at the end
# of the list to avoid a warning/error if no .d file exist # of the list to avoid a warning/error if no .d file exist
-include $(wildcard $(addsuffix /*.d,$(DEPDIRS))) /dev/null -include $(wildcard $(addsuffix /*.d,$(DEPDIRS))) /dev/null
$(PROFILE_STAMP): $(EXECUTABLE_PROFILE_GENERATE)
-rm -fr $(PROFILE_OUT)
$(STELLA_PROFILE_GENERATE)
touch $(PROFILE_STAMP)
# check if configure has been run or has been changed since last run # check if configure has been run or has been changed since last run
config.mak: $(srcdir)/configure config.mak: $(srcdir)/configure
@echo "You need to run ./configure before you can run make" @echo "You need to run ./configure before you can run make"

33
configure vendored
View File

@ -24,6 +24,7 @@ _build_joystick=yes
_build_cheats=yes _build_cheats=yes
_build_static=no _build_static=no
_build_profile=no _build_profile=no
_build_debug=no
# more defaults # more defaults
_ranlib=ranlib _ranlib=ranlib
@ -204,6 +205,8 @@ Optional Features:
--disable-static --disable-static
--enable-profile build binary with profiling info [disabled] --enable-profile build binary with profiling info [disabled]
--disable-profile --disable-profile
--enable-debug build with debugging symbols [disabled]
--disable-debug
--force-builtin-libpng force use of built-in libpng library [auto] --force-builtin-libpng force use of built-in libpng library [auto]
Optional Libraries: Optional Libraries:
@ -241,6 +244,8 @@ for ac_option in $@; do
--disable-static) _build_static=no ;; --disable-static) _build_static=no ;;
--enable-profile) _build_profile=yes ;; --enable-profile) _build_profile=yes ;;
--disable-profile) _build_profile=no ;; --disable-profile) _build_profile=no ;;
--enable-debug) _build_debug=yes ;;
--disable-debug) _build_debug=false ;;
--force-builtin-libpng) _libpng=no ;; --force-builtin-libpng) _libpng=no ;;
--with-sdl-prefix=*) --with-sdl-prefix=*)
arg=`echo $ac_option | cut -d '=' -f 2` arg=`echo $ac_option | cut -d '=' -f 2`
@ -404,6 +409,8 @@ if test "$have_clang" = yes; then
cxx_version="$cxx_version, bad" cxx_version="$cxx_version, bad"
cxx_verc_fail=yes cxx_verc_fail=yes
fi fi
_make_def_CLANG_WARNINGS='CLANG_WARNINGS = 1'
else else
# Need at least version 3.5 # Need at least version 3.5
if [ $clang_major -ge 4 ] || [ $clang_major -eq 3 -a $clang_minor -ge 5 ]; then if [ $clang_major -ge 4 ] || [ $clang_major -eq 3 -a $clang_minor -ge 5 ]; then
@ -420,9 +427,8 @@ if test "$have_clang" = yes; then
fi fi
fi fi
CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS"
_make_def_HAVE_GCC3='HAVE_GCC3 = 1' _make_def_HAVE_CLANG='HAVE_CLANG = 1'
add_line_to_config_mk 'CXX_UPDATE_DEP_FLAG = -MMD -MF "$(*D)/$(DEPDIR)/$(*F).d" -MQ "$@" -MP' add_line_to_config_mk 'CXX_UPDATE_DEP_FLAG = -MMD -MF "$(*D)/$(DEPDIR)/$(*F).d" -MQ "$@" -MP'
_make_def_HAVE_GCC='HAVE_GCC = 1'
echo "$cxx_version" echo "$cxx_version"
elif test "$have_gcc" = yes; then elif test "$have_gcc" = yes; then
@ -448,7 +454,6 @@ elif test "$have_gcc" = yes; then
;; ;;
esac esac
CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS"
_make_def_HAVE_GCC3='HAVE_GCC3 = 1'
add_line_to_config_mk 'CXX_UPDATE_DEP_FLAG = -MMD -MF "$(*D)/$(DEPDIR)/$(*F).d" -MQ "$@" -MP' add_line_to_config_mk 'CXX_UPDATE_DEP_FLAG = -MMD -MF "$(*D)/$(DEPDIR)/$(*F).d" -MQ "$@" -MP'
_make_def_HAVE_GCC='HAVE_GCC = 1' _make_def_HAVE_GCC='HAVE_GCC = 1'
echo "$cxx_version" echo "$cxx_version"
@ -670,11 +675,20 @@ fi
if test "$_build_profile" = yes ; then if test "$_build_profile" = yes ; then
echo_n " Profiling enabled" echo_n " Profiling enabled"
echo echo
_build_debug=yes
else else
echo_n " Profiling disabled" echo_n " Profiling disabled"
echo echo
fi fi
if test "$_build_debug" = yes ; then
echo_n " Debug symbols enabled"
echo
else
echo_n " Debug symbols disabled"
echo
fi
# #
# Now, add the appropriate defines/libraries/headers # Now, add the appropriate defines/libraries/headers
@ -774,6 +788,9 @@ if test "$_build_profile" = no ; then
_build_profile= _build_profile=
fi fi
if test "$_build_debug" = no ; then
_build_debug=
fi
echo "Creating config.mak" echo "Creating config.mak"
cat > config.mak << EOF cat > config.mak << EOF
@ -795,6 +812,8 @@ ZIP := $_zip
CP := $_cp CP := $_cp
WINDOWSPATH=$_windowspath WINDOWSPATH=$_windowspath
STRIP := $_strip STRIP := $_strip
LLVM_PROFDATA := llvm-profdata
BINARY_LOADER :=
MODULES += $MODULES MODULES += $MODULES
MODULE_DIRS += $MODULE_DIRS MODULE_DIRS += $MODULE_DIRS
@ -805,9 +824,10 @@ BINDIR := $_bindir
DOCDIR := $_docdir DOCDIR := $_docdir
DATADIR := $_datadir DATADIR := $_datadir
PROFILE := $_build_profile PROFILE := $_build_profile
DEBUG := $_build_debug
$_make_def_HAVE_GCC $_make_def_HAVE_GCC
$_make_def_HAVE_GCC3 $_make_def_HAVE_CLANG
$_make_def_CLANG_WARNINGS $_make_def_CLANG_WARNINGS
INCLUDES += $INCLUDES INCLUDES += $INCLUDES
@ -818,12 +838,11 @@ $_config_mk_data
EOF EOF
# This should be taken care of elsewhere, but I'm not sure where # This should be taken care of elsewhere, but I'm not sure where
rm -f stella-conf* rm -f stella-conf stella-conf.cxx
if test "$_host_os" = darwin; then if test "$_host_os" = darwin; then
cat <<EOI cat <<EOI
WARNING: plain UNIX-style builds on macOS without XCode have degraded functionality WARNING: plain UNIX-style builds on macOS without XCode are unsupported. Continue on your own risk...
and are unsupported. Continue on your own risk...
EOI EOI
fi fi

BIN
profile/128.bin Normal file

Binary file not shown.

4
profile/README.md Normal file
View File

@ -0,0 +1,4 @@
The ROMS that are used for profiling were created by and are by courtesy of
* Spiceware (`128.bin`)
* Kylearan (Catharsis Theory)

Binary file not shown.