From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!news.eternal-september.org!news.eternal-september.org!feeder.eternal-september.org!news.glorb.com!peer03.iad.highwinds-media.com!news.highwinds-media.com!feed-me.highwinds-media.com!peer03.am1!peering.am1!npeersf04.am4!fx24.fr7.POSTED!not-for-mail From: Brian Drummond Subject: Re: Exclude parts of a package Newsgroups: comp.lang.ada References: <52a0de7e$0$23162$2c885b36@post.eweka.nl> User-Agent: Pan/0.139 (Sexual Chocolate; GIT bf56508 git://git.gnome.org/pan2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Message-ID: NNTP-Posting-Host: 62.49.20.82 X-Complaints-To: abuse@demon.net X-Trace: 1386328470 62.49.20.82 (Fri, 06 Dec 2013 11:14:30 UTC) NNTP-Posting-Date: Fri, 06 Dec 2013 11:14:30 UTC Date: Fri, 06 Dec 2013 11:14:30 GMT X-Received-Body-CRC: 1358342070 X-Received-Bytes: 4829 Xref: news.eternal-september.org comp.lang.ada:17866 Date: 2013-12-06T11:14:30+00:00 List-Id: On Thu, 05 Dec 2013 21:13:50 +0100, Felix Krause wrote: > In C, I have the possibility to switch parts of my code on or off with > preprocessor defines. What would be the Ada way to do something like > that? > > I know that I can use scenario variables with gprbuild. This works well > if I want to include or exclude whole packages (because I can include or > exclude certain files), but it does not work if I just want to exclude > certain subroutines from a package. > > Take for example OpenCLAda: The user of the library should be able to > choose which version of the OpenCL API he wants to use (1.0, 1.1, …). > This choice should result in subroutines added in newer versions not > being available. I would tend to avoid the preprocessor - even the Gnat one - if at all possible. And I'm sure you will find it is possible. The basic idea is to separate out variant functionality into different packages for each revision - maybe OpenCL_1_0, OpenCL_1_1, etc. Then with/use a base package, OpenCL, in all your application code. When you come to build the program, you have to create the package OpenCL appropriately : it can be as simple as: with OpenCL_1_1; package Open_CL renames OpenCL_1_1; -------------------------------------------------------------------- In the MSP430 Ada compiler this approach is extended to support 450+ different varieties of the MSP430 embedded processor, each with a different set of peripherals, and the peripherals themselves vary, not just in register addresses but also functionality (e.g. 8 and 16 bit timers) Device selection is in package CPU.ads : with MSP.msp430g2553; package CPU renames MSP.msp430g2553; (Everything else - CPUs and peripherals are child packages of package MSP) package MSP is pragma Pure; type Byte is Array(0 .. 7) of Boolean; Pragma Pack(Byte); For Byte'Size use 8; ... end MSP; The specific CPU package, MSP.msp430g2553; looks like with MSP.cpu_5; with MSP.adc10; with MSP.port1_r_3; ... with MSP.ta3_1; with MSP.vectors_18; package MSP.msp430g2553 is pragma Preelaborate; package cpu renames MSP.cpu_5; package adc10 renames MSP.adc10; package port1_r renames MSP.port1_r_3; ... package ta3 renames MSP.ta3_1; package vectors renames MSP.vectors_18; end MSP.msp430g2553; as you can see, it selects the 5th variant of the CPU, the 3rd variant of Port 1 (a GPIO port) and the 18th variant of the interrupt vector table. There are 450 of these in the "cpu_support/cpus" folder. It turns out that there are 19 variants of package MSP.cpu, 5 of port1_r, and 84 variants of the interrupt vector table. A vector table package looks like: with Interfaces; use Interfaces; -- make unsigned_n visible package MSP.vectors_18 is pragma Preelaborate; port1_vector : constant unsigned_16 := 16#4#; port2_vector : constant unsigned_16 := 16#6#; adc10_vector : constant unsigned_16 := 16#A#; timer0_a0_vector : constant unsigned_16 := 16#12#; timer1_a1_vector : constant unsigned_16 := 16#18#; ... nmi_vector : constant unsigned_16 := 16#1C#; reset_vector : constant unsigned_16 := 16#1E#; end MSP.vectors_18; And finally a segment of an application : with CPU; procedure Watch is package Timer renames CPU.ta3; subtype TickCount is Interfaces.Unsigned_16; OneMinute : constant TickCount := 1024*60; begin Timer.ccr0 := OneMinute - 1; ... and so on. Now I can change package CPU with MSP.msp430g2202; package CPU renames MSP.msp430g2202; and recompile. If I have used any facilities missing in the new CPU, I find out at compile time. If the timer interrupt vector has been renamed package vectors renames MSP.vectors_28; The upshot of this approach is that