Commit 3549c952 authored by Herbert Valerio Riedel's avatar Herbert Valerio Riedel 🕺

Implement `MIN_VERSION_GLASGOW_HASKELL()` macro

This exposes the `cProjectPatchLevel{1,2}` value at the CPP level to
allow it to be used in CPP conditionals. Concretely, GHC 7.10.2.20150623
would result in

  #define __GLASGOW_HASKELL__             710
  #define __GLASGOW_HASKELL_PATCHLEVEL1__ 2
  #define __GLASGOW_HASKELL_PATCHLEVEL2__ 20150623

while GHC 7.10.3 results in

  #define __GLASGOW_HASKELL__             710
  #define __GLASGOW_HASKELL_PATCHLEVEL1__ 3

and finally GHC 7.9.20141009 results in

  #define __GLASGOW_HASKELL__             709
  #define __GLASGOW_HASKELL_PATCHLEVEL1__ 20141009

As it's error-prone to properly express CPP conditionals for testing GHC
multi-component versions, a new macro `MIN_VERSION_GLASGOW_HASKELL()` is
provided (also via the new CPP include file `ghcversion.h`)

Finally, in order to make it easier to define the new CPP macro
`MIN_VERSION_GLASGOW_HASKELL()`, a new default-included
`include/ghcversion.h` is used for the new CPP definitions.

Reviewed By: ekmett, austin, #ghc

Differential Revision: https://phabricator.haskell.org/D66
parent 2a8ea474
......@@ -103,6 +103,7 @@ _darcs/
/ghc/ghc-bin.cabal
/includes/ghcautoconf.h
/includes/ghcplatform.h
/includes/ghcversion.h
/index.html
/inplace/
/libffi/build/
......
......@@ -1604,6 +1604,13 @@ AC_SUBST([ProjectVersionInt])
# The project patchlevel is zero unless stated otherwise
test -z "$ProjectPatchLevel" && ProjectPatchLevel=0
# Save split version of ProjectPatchLevel
ProjectPatchLevel1=`echo $ProjectPatchLevel | sed 's/^\(@<:@^.@:>@*\)\(\.\{0,1\}\(.*\)\)$/\1/'`
ProjectPatchLevel2=`echo $ProjectPatchLevel | sed 's/^\(@<:@^.@:>@*\)\(\.\{0,1\}\(.*\)\)$/\3/'`
AC_SUBST([ProjectPatchLevel1])
AC_SUBST([ProjectPatchLevel2])
# Remove dots from the patch level; this allows us to have versions like 6.4.1.20050508
ProjectPatchLevel=`echo $ProjectPatchLevel | sed 's/\.//'`
......
......@@ -71,6 +71,10 @@ compiler/stage%/build/Config.hs : mk/config.mk mk/project.mk | $$(dir $$@)/.
@echo 'cProjectVersionInt = "$(ProjectVersionInt)"' >> $@
@echo 'cProjectPatchLevel :: String' >> $@
@echo 'cProjectPatchLevel = "$(ProjectPatchLevel)"' >> $@
@echo 'cProjectPatchLevel1 :: String' >> $@
@echo 'cProjectPatchLevel1 = "$(ProjectPatchLevel1)"' >> $@
@echo 'cProjectPatchLevel2 :: String' >> $@
@echo 'cProjectPatchLevel2 = "$(ProjectPatchLevel2)"' >> $@
@echo 'cBooterVersion :: String' >> $@
@echo 'cBooterVersion = "$(GhcVersion)"' >> $@
@echo 'cStage :: String' >> $@
......
......@@ -1089,6 +1089,8 @@ runPhase (RealPhase cc_phase) input_fn dflags
-- very weakly typed, being derived from C--.
["-fno-strict-aliasing"]
ghcVersionH <- liftIO $ getGhcVersionPathName dflags
let gcc_lang_opt | cc_phase `eqPhase` Ccpp = "c++"
| cc_phase `eqPhase` Cobjc = "objective-c"
| cc_phase `eqPhase` Cobjcpp = "objective-c++"
......@@ -1138,7 +1140,9 @@ runPhase (RealPhase cc_phase) input_fn dflags
++ verbFlags
++ [ "-S" ]
++ cc_opt
++ [ "-D__GLASGOW_HASKELL__="++cProjectVersionInt ]
++ [ "-D__GLASGOW_HASKELL__="++cProjectVersionInt
, "-include", ghcVersionH
]
++ framework_paths
++ split_opt
++ include_paths
......@@ -2092,6 +2096,13 @@ doCpp dflags raw input_fn output_fn = do
backend_defs <- getBackendDefs dflags
-- Default CPP defines in Haskell source
ghcVersionH <- getGhcVersionPathName dflags
let hsSourceCppOpts =
[ "-D__GLASGOW_HASKELL__="++cProjectVersionInt
, "-include", ghcVersionH
]
cpp_prog ( map SysTools.Option verbFlags
++ map SysTools.Option include_paths
++ map SysTools.Option hsSourceCppOpts
......@@ -2129,11 +2140,6 @@ getBackendDefs dflags | hscTarget dflags == HscLlvm = do
getBackendDefs _ =
return []
hsSourceCppOpts :: [String]
-- Default CPP defines in Haskell source
hsSourceCppOpts =
[ "-D__GLASGOW_HASKELL__="++cProjectVersionInt ]
-- ---------------------------------------------------------------------------
-- join object files into a single relocatable object file, using ld -r
......@@ -2213,6 +2219,16 @@ haveRtsOptsFlags dflags =
RtsOptsSafeOnly -> False
_ -> True
-- | Find out path to @ghcversion.h@ file
getGhcVersionPathName :: DynFlags -> IO FilePath
getGhcVersionPathName dflags = do
dirs <- getPackageIncludePath dflags [rtsPackageKey]
found <- filterM doesFileExist (map (</> "ghcversion.h") dirs)
case found of
[] -> throwGhcExceptionIO (InstallationError ("ghcversion.h missing"))
(x:_) -> return x
-- Note [-fPIC for assembler]
-- When compiling .c source file GHC's driver pipeline basically
-- does the following two things:
......
......@@ -387,6 +387,85 @@ $ cat foo.hspp</screen>
</listitem>
</varlistentry>
<varlistentry>
<term>
<constant>&lowbar;&lowbar;GLASGOW&lowbar;HASKELL&lowbar;PATCHLEVEL1&lowbar;&lowbar;</constant>
<indexterm><primary><constant>&lowbar;&lowbar;GLASGOW&lowbar;HASKELL&lowbar;PATCHLEVEL1&lowbar;&lowbar;</constant></primary></indexterm>
</term>
<term>
<constant>&lowbar;&lowbar;GLASGOW&lowbar;HASKELL&lowbar;PATCHLEVEL2&lowbar;&lowbar;</constant>
<indexterm><primary><constant>&lowbar;&lowbar;GLASGOW&lowbar;HASKELL&lowbar;PATCHLEVEL2&lowbar;&lowbar;</constant></primary></indexterm>
</term>
<listitem>
<para>These macros are available starting with GHC 7.10.1.</para>
<para>For three-part GHC version numbers
<literal><replaceable>x</replaceable>.<replaceable>y</replaceable>.<replaceable>z</replaceable></literal>,
the value of
<constant>&lowbar;&lowbar;GLASGOW&lowbar;HASKELL&lowbar;PATCHLEVEL1&lowbar;&lowbar;</constant>
is the integer <replaceable>z</replaceable>.</para>
<para>For four-part GHC version numbers
<literal><replaceable>x</replaceable>.<replaceable>y</replaceable>.<replaceable>z</replaceable>.<replaceable>z'</replaceable></literal>,
the value of
<constant>&lowbar;&lowbar;GLASGOW&lowbar;HASKELL&lowbar;PATCHLEVEL1&lowbar;&lowbar;</constant>
is the integer <replaceable>z</replaceable> while the value of
<constant>&lowbar;&lowbar;GLASGOW&lowbar;HASKELL&lowbar;PATCHLEVEL2&lowbar;&lowbar;</constant>
is set to the integer <replaceable>z'</replaceable>.</para>
<para>These macros are provided for allowing finer
granularity than is provided by
<literal>__GLASGOW_HASKELL__</literal>. Usually, this should
not be necessary as it's expected for most APIs to remain
stable between patchlevel releases, but occasionally
internal API changes are necessary to fix bugs. Also
conditional compilation on the patchlevel can be useful for
working around bugs in older releases.</para>
<para>NB. These macros are set when pre-processing both
Haskell source and C source, including the C source
generated from a Haskell module
(i.e. <filename>.hs</filename>, <filename>.lhs</filename>,
<filename>.c</filename> and <filename>.hc</filename>
files).</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<constant>MIN&lowbar;VERSION&lowbar;GLASGOW&lowbar;HASKELL(<replaceable>x</replaceable>,<replaceable>y</replaceable>,<replaceable>z</replaceable>,<replaceable>z'</replaceable>)</constant>
<indexterm><primary><constant>MIN&lowbar;VERSION&lowbar;GLASGOW&lowbar;HASKELL</constant></primary></indexterm>
</term>
<listitem>
<para>This macro is available starting with GHC 7.10.1.</para>
<para>This macro is provided for convenience to write CPP
conditionals testing whether the GHC version used is version
<literal><replaceable>x</replaceable>.<replaceable>y</replaceable>.<replaceable>z</replaceable>.<replaceable>z'</replaceable></literal>
or later.</para>
<para>If compatibility with Haskell compilers (including GHC
prior to version 7.10.1) which do not define
<literal>MIN_VERSION_GLASGOW_HASKELL</literal> is required,
the presence of the
<literal>MIN_VERSION_GLASGOW_HASKELL</literal> macro needs
to be ensured before it is called, e.g.:</para>
<programlisting>&num;ifdef MIN_VERSION_GLASGOW_HASKELL
&num;if MIN_VERSION_GLASGOW_HASKELL(7,10,2,0)
/* code that applies only to GHC 7.10.2 or later */
&num;endif
&num;endif</programlisting>
<para>NB. This macro is set when pre-processing both
Haskell source and C source, including the C source
generated from a Haskell module
(i.e. <filename>.hs</filename>, <filename>.lhs</filename>,
<filename>.c</filename> and <filename>.hc</filename>
files).</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<constant>&lowbar;&lowbar;GLASGOW&lowbar;HASKELL&lowbar;LLVM&lowbar;&lowbar;</constant>
......
......@@ -1223,6 +1223,7 @@ CLEAN_FILES += includes/GHCConstants.h
CLEAN_FILES += includes/DerivedConstants.h
CLEAN_FILES += includes/ghcautoconf.h
CLEAN_FILES += includes/ghcplatform.h
CLEAN_FILES += includes/ghcversion.h
CLEAN_FILES += utils/ghc-pkg/Version.hs
CLEAN_FILES += compiler/parser/Parser.y
CLEAN_FILES += compiler/prelude/primops.txt
......
......@@ -16,6 +16,7 @@
# XXX: these should go in includes/dist/build?
includes_H_CONFIG = includes/ghcautoconf.h
includes_H_PLATFORM = includes/ghcplatform.h
includes_H_VERSION = includes/ghcversion.h
#
# All header files are in includes/{one of these subdirectories}
......@@ -53,6 +54,34 @@ ifeq "$(DYNAMIC_BY_DEFAULT)" "YES"
includes_CC_OPTS += -DDYNAMIC_BY_DEFAULT
endif
$(includes_H_VERSION) : mk/project.mk | $$(dir $$@)/.
@echo "Creating $@..."
@echo "#ifndef __GHCVERSION_H__" > $@
@echo "#define __GHCVERSION_H__" >> $@
@echo >> $@
@echo "#ifndef __GLASGOW_HASKELL__" >> $@
@echo "# define __GLASGOW_HASKELL__ $(ProjectVersionInt)" >> $@
@echo "#endif" >> $@
@echo >> $@
@if [ -n "$(ProjectPatchLevel1)" ]; then \
echo "#define __GLASGOW_HASKELL_PATCHLEVEL1__ $(ProjectPatchLevel1)" >> $@; \
fi
@if [ -n "$(ProjectPatchLevel2)" ]; then \
echo "#define __GLASGOW_HASKELL_PATCHLEVEL1__ $(ProjectPatchLevel2)" >> $@; \
fi
@echo >> $@
@echo '#define MIN_VERSION_GLASGOW_HASKELL(ma,mi,pl1,pl2) (\\' >> $@
@echo ' ((ma)*100+(mi)) < __GLASGOW_HASKELL__ || \\' >> $@
@echo ' ((ma)*100+(mi)) == __GLASGOW_HASKELL__ \\' >> $@
@echo ' && (pl1) < __GLASGOW_HASKELL_PATCHLEVEL1__ || \\'>> $@
@echo ' ((ma)*100+(mi)) == __GLASGOW_HASKELL__ \\' >> $@
@echo ' && (pl1) == __GLASGOW_HASKELL_PATCHLEVEL1__ \\' >> $@
@echo ' && (pl2) <= __GLASGOW_HASKELL_PATCHLEVEL2__ )' >> $@
@echo >> $@
@echo "#endif /* __GHCVERSION_H__ */" >> $@
@echo "Done."
ifneq "$(BINDIST)" "YES"
ifeq "$(PORTING_HOST)" "YES"
......@@ -160,8 +189,8 @@ DERIVE_CONSTANTS_FLAGS += $(addprefix --gcc-flag$(space),$(includes_CC_OPTS) -fc
DERIVE_CONSTANTS_FLAGS += --nm-program "$(NM)"
ifneq "$(BINDIST)" "YES"
$(includes_DERIVEDCONSTANTS): $$(includes_H_CONFIG) $$(includes_H_PLATFORM) $$(includes_H_FILES) $$(rts_H_FILES)
$(includes_GHCCONSTANTS_HASKELL_VALUE): $$(includes_H_CONFIG) $$(includes_H_PLATFORM) $$(includes_H_FILES) $$(rts_H_FILES)
$(includes_DERIVEDCONSTANTS): $$(includes_H_CONFIG) $$(includes_H_PLATFORM) $$(includes_H_VERSION) $$(includes_H_FILES) $$(rts_H_FILES)
$(includes_GHCCONSTANTS_HASKELL_VALUE): $$(includes_H_CONFIG) $$(includes_H_PLATFORM) $$(includes_H_VERSION) $$(includes_H_FILES) $$(rts_H_FILES)
$(includes_DERIVEDCONSTANTS): $(deriveConstants_INPLACE) | $$(dir $$@)/.
$< --gen-header -o $@ --tmpdir $(dir $@) $(DERIVE_CONSTANTS_FLAGS)
......@@ -183,10 +212,10 @@ endif
# Install all header files
$(eval $(call clean-target,includes,,\
$(includes_H_CONFIG) $(includes_H_PLATFORM)))
$(includes_H_CONFIG) $(includes_H_PLATFORM) $(includes_H_VERSION)))
$(eval $(call all-target,includes,\
$(includes_H_CONFIG) $(includes_H_PLATFORM) \
$(includes_H_CONFIG) $(includes_H_PLATFORM) $(includes_H_VERSION) \
$(includes_GHCCONSTANTS_HASKELL_TYPE) \
$(includes_GHCCONSTANTS_HASKELL_VALUE) \
$(includes_GHCCONSTANTS_HASKELL_WRAPPERS) \
......@@ -202,5 +231,5 @@ install_includes :
$(call INSTALL_DIR,"$(DESTDIR)$(ghcheaderdir)/$d") && \
$(call INSTALL_HEADER,$(INSTALL_OPTS),includes/$d/*.h,"$(DESTDIR)$(ghcheaderdir)/$d/") && \
) true
$(call INSTALL_HEADER,$(INSTALL_OPTS),$(includes_H_CONFIG) $(includes_H_PLATFORM) $(includes_DERIVEDCONSTANTS),"$(DESTDIR)$(ghcheaderdir)/")
$(call INSTALL_HEADER,$(INSTALL_OPTS),$(includes_H_CONFIG) $(includes_H_PLATFORM) $(includes_H_VERSION) $(includes_DERIVEDCONSTANTS),"$(DESTDIR)$(ghcheaderdir)/")
......@@ -29,6 +29,8 @@ ProjectTags =
ProjectVersion = @ProjectVersion@$(ProjectTags)
ProjectVersionInt = @ProjectVersionInt@
ProjectPatchLevel = @ProjectPatchLevel@
ProjectPatchLevel1 = @ProjectPatchLevel1@
ProjectPatchLevel2 = @ProjectPatchLevel2@
################################################################################
#
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment