driver-avr.c revision 1.6
1/* Subroutines for the gcc driver.
2   Copyright (C) 2009-2016 Free Software Foundation, Inc.
3   Contributed by Georg-Johann Lay <avr@gjlay.de>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3.  If not see
19<http://www.gnu.org/licenses/>.  */
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "diagnostic.h"
25#include "tm.h"
26
27// Remove -nodevicelib from the command line if not needed
28#define X_NODEVLIB "%<nodevicelib"
29
30static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
31
32static const char specfiles_doc_url[] =
33  "http://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html";
34
35
36static const char*
37avr_diagnose_devicespecs_error (const char *mcu, const char *filename)
38{
39  error ("cannot access device-specs for %qs expected at %qs",
40         mcu, filename);
41
42  // Inform about natively supported devices and cores.
43
44  if (strncmp (mcu, "avr", strlen ("avr")))
45    avr_inform_devices ();
46
47  avr_inform_core_architectures ();
48
49  inform (input_location, "you can provide your own specs files, "
50          "see <%s> for details", specfiles_doc_url);
51
52  return X_NODEVLIB;
53}
54
55
56/* Implement spec function `device-specs-file��.
57
58   Compose -specs=<specs-file-name>%s.  If everything went well then argv[0]
59   is the inflated (absolute) specs directory and argv[1] is a device or
60   core name as supplied by -mmcu=*.  When building GCC the path might
61   be relative.  */
62
63const char*
64avr_devicespecs_file (int argc, const char **argv)
65{
66  char *specfile_name;
67  const char *mmcu = NULL;
68
69#ifdef DEBUG_SPECS
70  if (verbose_flag)
71    fnotice (stderr, "Running spec function '%s' with %d args\n\n",
72             __FUNCTION__, argc);
73#endif
74
75  switch (argc)
76    {
77    case 0:
78      fatal_error (input_location,
79                   "bad usage of spec function %qs", "device-specs-file");
80      return X_NODEVLIB;
81
82    case 1:
83      if (0 == strcmp ("device-specs", argv[0]))
84        {
85          /* FIXME:  This means "device-specs%s" from avr.h:DRIVER_SELF_SPECS
86             has not been resolved to a path.  That case can occur when the
87             c++ testsuite is run from the build directory.  DejaGNU's
88             libgloss.exp:get_multilibs runs $compiler without -B, i.e.runs
89             xgcc without specifying a prefix.  Without any prefix, there is
90             no means to find out where the specs files might be located.
91             get_multilibs runs xgcc --print-multi-lib, hence we don't actually
92             need information form a specs file and may skip it here.  */
93          return X_NODEVLIB;
94        }
95
96      mmcu = AVR_MMCU_DEFAULT;
97      break;
98
99    default:
100      mmcu = argv[1];
101
102      // Allow specifying the same MCU more than once.
103
104      for (int i = 2; i < argc; i++)
105        if (0 != strcmp (mmcu, argv[i]))
106          {
107            error ("specified option %qs more than once", "-mmcu");
108            return X_NODEVLIB;
109          }
110
111      break;
112    }
113
114  specfile_name = concat (argv[0], dir_separator_str, "specs-", mmcu, NULL);
115
116#ifdef DEBUG_SPECS
117  if (verbose_flag)
118    fnotice (stderr, "'%s': mmcu='%s'\n'%s': specfile='%s'\n\n",
119             __FUNCTION__, mmcu, __FUNCTION__, specfile_name);
120#endif
121
122  // Filter out silly -mmcu= arguments like "foo bar".
123
124  for (const char *s = mmcu; *s; s++)
125    if (!ISALNUM (*s)
126        && '-' != *s
127        && '_' != *s)
128      {
129        error ("strange device name %qs after %qs: bad character %qc",
130               mmcu, "-mmcu=", *s);
131        return X_NODEVLIB;
132      }
133
134  if (/* When building / configuring the compiler we might get a relative path
135         as supplied by "-B.".  Assume that the specs file exists and MCU is
136         a core, not a proper device then, i.e. we have "-mmcu=avr*".  */
137      (0 == strncmp (mmcu, "avr", strlen ("avr"))
138       && specfile_name[0] == '.')
139      /* vanilla */
140      || (IS_ABSOLUTE_PATH (specfile_name)
141          && !access (specfile_name, R_OK)))
142    {
143      return concat ("-specs=device-specs", dir_separator_str, "specs-", mmcu,
144                     // Use '%s' instead of the expanded specfile_name.  This
145                     // is the easiest way to handle pathes containing spaces.
146                     "%s",
147#if defined (WITH_AVRLIBC)
148                     " %{mmcu=avr*:" X_NODEVLIB "} %{!mmcu=*:" X_NODEVLIB "}",
149#else
150                     " " X_NODEVLIB,
151#endif
152                     NULL);
153    }
154
155  return avr_diagnose_devicespecs_error (mmcu, specfile_name);
156}
157