Skip to content

Commit

Permalink
Add handling of erlang version based compiler macros
Browse files Browse the repository at this point in the history
The mechanism has been copied from LFE and is more general than
necessary here but this makes it easier to maintain. We are even
future rebar compliant.
  • Loading branch information
rvirding committed Aug 8, 2016
1 parent 52feb45 commit cc84d24
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 24 deletions.
54 changes: 30 additions & 24 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2014 Robert Virding
# Copyright (c) 2016 Robert Virding
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -12,41 +12,47 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# Luerl Makefile
# Makefile for Luerl
# Building from .xrl, .yrl and .erl
# Intermediaries from leex and yecc stay in ./src

SRCDIR =./src
BEAMDIR =./ebin
ERL_SOURCES := $(wildcard $(SRCDIR)/*.erl)
XRL_SOURCES := $(wildcard $(SRCDIR)/*.xrl)
YRL_SOURCES := $(wildcard $(SRCDIR)/*.yrl)
ERL_MODULES := $(ERL_SOURCES:$(SRCDIR)/%.erl=%)
XRL_MODULES := $(XRL_SOURCES:$(SRCDIR)/%.xrl=%)
YRL_MODULES := $(YRL_SOURCES:$(SRCDIR)/%.yrl=%)
XRL_INTERM := $(XRL_MODULES:%=$(SRCDIR)/%.erl)
YRL_INTERM := $(YRL_MODULES:%=$(SRCDIR)/%.erl)
MODULES := $(XRL_MODULES) $(YRL_MODULES) $(ERL_MODULES)
OBJECTS := $(MODULES:%=$(BEAMDIR)/%.beam)

all: $(OBJECTS)

$(BEAMDIR)/%.beam: $(SRCDIR)/%.erl $(SRCDIR)/luerl.hrl
@ mkdir -p $(BEAMDIR)
erlc $(ERLCFLAGS) -o $(BEAMDIR) $<
EBINDIR =./ebin

ESRCS := $(notdir $(wildcard $(SRCDIR)/*.erl))
XSRCS := $(notdir $(wildcard $(SRCDIR)/*.xrl))
YSRCS := $(notdir $(wildcard $(SRCDIR)/*.yrl))
EBINS = $(ESRCS:.erl=.beam) $(XSRCS:.xrl=.beam) $(YSRCS:.yrl=.beam)

ERLCFLAGS = -W1
ERLC = erlc

all: compile

.PHONY: compile clean echo examples

compile: comp_opts.mk $(addprefix $(EBINDIR)/, $(EBINS))

$(EBINDIR)/%.beam: $(SRCDIR)/%.erl $(SRCDIR)/luerl.hrl comp_opts.mk
@ mkdir -p $(EBINDIR)
$(ERLC) $(ERLCFLAGS) -o $(EBINDIR) $(COMP_OPTS) $(ERLCFLAGS) $<

%.erl: %.xrl
erlc -o $(SRCDIR) $<
$(ERLC) -o $(SRCDIR) $<

%.erl: %.yrl
erlc -o $(SRCDIR) $<
$(ERLC) -o $(SRCDIR) $<

comp_opts.mk:
escript get_comp_opts.escript

-include comp_opts.mk

clean:
@ rm -f $(BEAMDIR)/*.beam
@ rm -f $(EBINDIR)/*.beam
@ rm -f *.beam
@ rm -f erl_crash.dump
@ rm -f $(XRL_INTERM)
@ rm -f $(YRL_INTERM)
@ rm comp_opts.mk
$(MAKE) -C examples clean

echo:
Expand Down
48 changes: 48 additions & 0 deletions get_comp_opts.escript
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#! /usr/bin/env escript
%% -*- mode: erlang; indent-tabs-mode: nil -*-
%% Define a number of compiler options. We first work out the current
%% Erlang version and from the we can define the various options.

%% Bloody useful.
-define(IF(Test,True,False), case Test of true -> True; false -> False end).

%% Define the makefile variables HAS_MAPS and HAS_FULL_KEYS depending
%% on whether this version of erlang has maps (17) and general map
%% keys (18), or NEW_CORE_REC for new core definition of records (19).

-define(HAS_MAPS_OPT, "-DHAS_MAPS=true").
-define(FULL_KEYS_OPT, "-DHAS_FULL_KEYS=true").
-define(NEW_REC_OPT, "-DNEW_REC_CORE=true").
-define(NEW_RAND_OPT, "-DNEW_RAND=true").

main(_) ->
Version = otp_release(),
CompOpts = comp_opts(Version),
file:write_file("comp_opts.mk", "COMP_OPTS = " ++ CompOpts ++ "\n").

comp_opts(Version) ->
Copts0 = "-DERLANG_VERSION=" ++ Version,
Copts1 = ?IF(Version >= "17", Copts0 ++ " " ++ ?HAS_MAPS_OPT, Copts0),
Copts2 = ?IF(Version >= "18", Copts1 ++ " " ++ ?FULL_KEYS_OPT, Copts1),
Copts3 = ?IF(Version >= "19",
Copts2 ++ append_copts([?NEW_REC_OPT,?NEW_RAND_OPT]),
Copts2),
Copts3.

append_copts([Copt|Copts]) ->
" " ++ Copt ++ append_copts(Copts);
append_copts([]) -> [].

%% Get the major release number.
%% We have stolen the idea for this code from rebar3.

otp_release() ->
case erlang:system_info(otp_release) of
[$R,N1,N2|_] when is_integer(N1), is_integer(N2) ->
%% If OTP <= R16, take the digits.
[N1,N2];
Rel ->
%% If OTP >= 17.x, erlang:system_info(otp_release) returns just
%% the major version number.
Rel
end.
33 changes: 33 additions & 0 deletions rebar.config.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
%% -*- mode: erlang; indent-tabs-mode: nil -*-

Conf0 = CONFIG,
HasOpt = {d,'HAS_MAPS',true},
FullOpt = {d,'HAS_FULL_KEYS',true},
RecOpt = {d,'NEW_REC_CORE',true},
RandOpt = {d,'NEW_RAND',true},

Version = case erlang:system_info(otp_release) of
[$R,N1,N2|_] when is_integer(N1), is_integer(N2) ->
[N1,N2];
Rel -> Rel
end,

Copts0 = [{d,'ERLANG_VERSION',Version}],
Copts1 = if Version >= "17" -> Copts0 ++ [HasOpt];
true -> Copts0
end,
Copts2 = if Version >= "18" -> Copts1 ++ [FullOpt];
true -> Copts1
end,
Copts3 = if Version >= "19" -> Copts2 ++ [RecOpt,RandOpt];
true -> Copts2
end,
Copts = Copts3, %This is it

case lists:keyfind(erl_opts, 1, Conf0) of
{erl_opts,Opts} -> %Existing erl_opts
NewOpts = {erl_opts,Opts ++ Copts},
lists:keyreplace(erl_opts, 1, Conf0, NewOpts);
false -> %No erl_opts
Conf0 ++ [{erl_opts,Copts}]
end.

0 comments on commit cc84d24

Please sign in to comment.