]>
Commit | Line | Data |
---|---|---|
4a2caf6c | 1 | /* Subroutines for the gcc driver. |
818ab71a | 2 | Copyright (C) 2009-2016 Free Software Foundation, Inc. |
4a2caf6c GJL |
3 | Contributed by Georg-Johann Lay <avr@gjlay.de> |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along 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 | ||
076d86f3 GJL |
27 | // Remove -nodevicelib from the command line if not needed |
28 | #define X_NODEVLIB "%<nodevicelib" | |
29 | ||
4a2caf6c GJL |
30 | static const char dir_separator_str[] = { DIR_SEPARATOR, 0 }; |
31 | ||
32 | static const char specfiles_doc_url[] = | |
33 | "http://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html"; | |
34 | ||
35 | ||
36 | static const char* | |
37 | avr_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 | ||
076d86f3 | 52 | return X_NODEVLIB; |
4a2caf6c GJL |
53 | } |
54 | ||
55 | ||
56 | /* Implement spec function `device-specs-fileĀ“. | |
57 | ||
ed137300 GJL |
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. */ | |
4a2caf6c GJL |
62 | |
63 | const char* | |
64 | avr_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"); | |
076d86f3 | 80 | return X_NODEVLIB; |
4a2caf6c GJL |
81 | |
82 | case 1: | |
3184f36f GJL |
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 | ||
4a2caf6c GJL |
96 | mmcu = AVR_MMCU_DEFAULT; |
97 | break; | |
98 | ||
ed137300 | 99 | default: |
4a2caf6c | 100 | mmcu = argv[1]; |
4a2caf6c | 101 | |
ed137300 GJL |
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; | |
4a2caf6c GJL |
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); | |
076d86f3 | 131 | return X_NODEVLIB; |
4a2caf6c GJL |
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 | { | |
076d86f3 GJL |
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); | |
4a2caf6c GJL |
153 | } |
154 | ||
155 | return avr_diagnose_devicespecs_error (mmcu, specfile_name); | |
156 | } |