1 /* ide-toolchain.c
2 *
3 * Copyright 2018 Collabora Ltd.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Authors: Corentin Noël <corentin.noel@collabora.com>
19 *
20 * SPDX-License-Identifier: GPL-3.0-or-later
21 */
22
23 #define G_LOG_DOMAIN "ide-toolchain"
24
25 #include "config.h"
26
27 #include "ide-toolchain.h"
28 #include "ide-triplet.h"
29
30 typedef struct
31 {
32 gchar *id;
33 gchar *display_name;
34 IdeTriplet *host_triplet;
35 } IdeToolchainPrivate;
36
37 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (IdeToolchain, ide_toolchain, IDE_TYPE_OBJECT)
38
39 enum {
40 PROP_0,
41 PROP_ID,
42 PROP_DISPLAY_NAME,
43 PROP_HOST_TRIPLET,
44 N_PROPS
45 };
46
47 static GParamSpec *properties [N_PROPS];
48
49 /**
50 * ide_toolchain_get_id:
51 * @self: an #IdeToolchain
52 *
53 * Gets the internal identifier of the toolchain
54 *
55 * Returns: (transfer none): the unique identifier.
56 *
57 * Since: 3.32
58 */
59 const gchar *
ide_toolchain_get_id(IdeToolchain * self)60 ide_toolchain_get_id (IdeToolchain *self)
61 {
62 IdeToolchainPrivate *priv = ide_toolchain_get_instance_private (self);
63
64 g_return_val_if_fail (IDE_IS_TOOLCHAIN (self), NULL);
65
66 return priv->id;
67 }
68
69
70 /**
71 * ide_toolchain_set_id:
72 * @self: an #IdeToolchain
73 * @id: the unique identifier
74 *
75 * Sets the internal identifier of the toolchain
76 *
77 * Since: 3.32
78 */
79 void
ide_toolchain_set_id(IdeToolchain * self,const gchar * id)80 ide_toolchain_set_id (IdeToolchain *self,
81 const gchar *id)
82 {
83 IdeToolchainPrivate *priv = ide_toolchain_get_instance_private (self);
84
85 g_return_if_fail (IDE_IS_TOOLCHAIN (self));
86 g_return_if_fail (id != NULL);
87
88 if (g_strcmp0 (id, priv->id) != 0)
89 {
90 g_clear_pointer (&priv->id, g_free);
91 priv->id = g_strdup (id);
92 g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ID]);
93 }
94 }
95
96 const gchar *
ide_toolchain_get_display_name(IdeToolchain * self)97 ide_toolchain_get_display_name (IdeToolchain *self)
98 {
99 IdeToolchainPrivate *priv = ide_toolchain_get_instance_private (self);
100
101 g_return_val_if_fail (IDE_IS_TOOLCHAIN (self), NULL);
102
103 return priv->display_name;
104 }
105
106 void
ide_toolchain_set_display_name(IdeToolchain * self,const gchar * display_name)107 ide_toolchain_set_display_name (IdeToolchain *self,
108 const gchar *display_name)
109 {
110 IdeToolchainPrivate *priv = ide_toolchain_get_instance_private (self);
111
112 g_return_if_fail (IDE_IS_TOOLCHAIN (self));
113 g_return_if_fail (display_name != NULL);
114
115 if (g_strcmp0 (display_name, priv->display_name) != 0)
116 {
117 g_clear_pointer (&priv->display_name, g_free);
118 priv->display_name = g_strdup (display_name);
119 g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DISPLAY_NAME]);
120 }
121 }
122
123 /**
124 * ide_toolchain_set_host_triplet:
125 * @self: an #IdeToolchain
126 * @host_triplet: an #IdeTriplet representing the host architecture of the toolchain
127 *
128 * Sets the host system of the toolchain
129 *
130 * Since: 3.32
131 */
132 void
ide_toolchain_set_host_triplet(IdeToolchain * self,IdeTriplet * host_triplet)133 ide_toolchain_set_host_triplet (IdeToolchain *self,
134 IdeTriplet *host_triplet)
135 {
136 IdeToolchainPrivate *priv = ide_toolchain_get_instance_private (self);
137
138 g_return_if_fail (IDE_IS_TOOLCHAIN (self));
139
140 if (host_triplet != priv->host_triplet)
141 {
142 g_clear_pointer (&priv->host_triplet, ide_triplet_unref);
143 priv->host_triplet = ide_triplet_ref (host_triplet);
144 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HOST_TRIPLET]);
145 }
146 }
147
148 /**
149 * ide_toolchain_get_host_triplet:
150 * @self: an #IdeToolchain
151 *
152 * Gets the combination of arch-kernel-system, sometimes referred to as
153 * the "host triplet".
154 *
155 * For Linux based devices, this will generally be something like
156 * "x86_64-linux-gnu".
157 *
158 * Returns: (transfer full): The host system.type of the toolchain
159 *
160 * Since: 3.32
161 */
162 IdeTriplet *
ide_toolchain_get_host_triplet(IdeToolchain * self)163 ide_toolchain_get_host_triplet (IdeToolchain *self)
164 {
165 IdeToolchainPrivate *priv = ide_toolchain_get_instance_private (self);
166
167 g_return_val_if_fail (IDE_IS_TOOLCHAIN (self), NULL);
168
169 return ide_triplet_ref (priv->host_triplet);
170 }
171
172 static const gchar *
ide_toolchain_real_get_tool_for_language(IdeToolchain * self,const gchar * language,const gchar * tool_id)173 ide_toolchain_real_get_tool_for_language (IdeToolchain *self,
174 const gchar *language,
175 const gchar *tool_id)
176 {
177 g_return_val_if_fail (IDE_IS_TOOLCHAIN (self), NULL);
178
179 g_critical ("%s has not implemented get_tool_for_language()", G_OBJECT_TYPE_NAME (self));
180
181 return NULL;
182 }
183
184 static GHashTable *
ide_toolchain_real_get_tools_for_id(IdeToolchain * self,const gchar * tool_id)185 ide_toolchain_real_get_tools_for_id (IdeToolchain *self,
186 const gchar *tool_id)
187 {
188 g_return_val_if_fail (IDE_IS_TOOLCHAIN (self), NULL);
189
190 g_critical ("%s has not implemented get_tools_for_id()", G_OBJECT_TYPE_NAME (self));
191
192 return NULL;
193 }
194
195 /**
196 * ide_toolchain_get_tool_for_language:
197 * @self: an #IdeToolchain
198 * @language: the language of the tool like %IDE_TOOLCHAIN_LANGUAGE_C.
199 * @tool_id: the identifier of the tool like %IDE_TOOLCHAIN_TOOL_CC
200 *
201 * Gets the path of the specified tool for the requested language.
202 * If %IDE_TOOLCHAIN_LANGUAGE_ANY is used in the @language field, the first tool matching @tool_id
203 * will be returned.
204 *
205 * Returns: (transfer none): A string containing the path of the tool for the given language, or
206 * %NULL is no tool has been found.
207 *
208 * Since: 3.32
209 */
210 const gchar *
ide_toolchain_get_tool_for_language(IdeToolchain * self,const gchar * language,const gchar * tool_id)211 ide_toolchain_get_tool_for_language (IdeToolchain *self,
212 const gchar *language,
213 const gchar *tool_id)
214 {
215 const gchar *ret;
216
217 IDE_ENTRY;
218
219 g_return_val_if_fail (IDE_IS_TOOLCHAIN (self), NULL);
220
221 ret = IDE_TOOLCHAIN_GET_CLASS (self)->get_tool_for_language (self, language, tool_id);
222
223 IDE_RETURN (ret);
224 }
225
226 /**
227 * ide_toolchain_get_tools_for_id:
228 * @self: an #IdeToolchain
229 * @tool_id: the identifier of the tool like %IDE_TOOLCHAIN_TOOL_CC
230 *
231 * Gets the list of all the paths to the specified tool id.
232 *
233 * Returns: (transfer full) (element-type utf8 utf8): A table of language names and paths.
234 *
235 * Since: 3.32
236 */
237 GHashTable *
ide_toolchain_get_tools_for_id(IdeToolchain * self,const gchar * tool_id)238 ide_toolchain_get_tools_for_id (IdeToolchain *self,
239 const gchar *tool_id)
240 {
241 GHashTable *ret;
242
243 IDE_ENTRY;
244
245 g_return_val_if_fail (IDE_IS_TOOLCHAIN (self), NULL);
246
247 ret = IDE_TOOLCHAIN_GET_CLASS (self)->get_tools_for_id (self, tool_id);
248
249 IDE_RETURN (ret);
250 }
251
252 static void
ide_toolchain_finalize(GObject * object)253 ide_toolchain_finalize (GObject *object)
254 {
255 IdeToolchain *self = (IdeToolchain *)object;
256 IdeToolchainPrivate *priv = ide_toolchain_get_instance_private (self);
257
258 g_clear_pointer (&priv->id, g_free);
259 g_clear_pointer (&priv->display_name, g_free);
260 g_clear_pointer (&priv->host_triplet, ide_triplet_unref);
261
262 G_OBJECT_CLASS (ide_toolchain_parent_class)->finalize (object);
263 }
264
265 static void
ide_toolchain_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)266 ide_toolchain_get_property (GObject *object,
267 guint prop_id,
268 GValue *value,
269 GParamSpec *pspec)
270 {
271 IdeToolchain *self = IDE_TOOLCHAIN (object);
272
273 switch (prop_id)
274 {
275 case PROP_ID:
276 g_value_set_string (value, ide_toolchain_get_id (self));
277 break;
278 case PROP_DISPLAY_NAME:
279 g_value_set_string (value, ide_toolchain_get_display_name (self));
280 break;
281 case PROP_HOST_TRIPLET:
282 g_value_set_boxed (value, ide_toolchain_get_host_triplet (self));
283 break;
284 default:
285 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
286 }
287 }
288
289 static void
ide_toolchain_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)290 ide_toolchain_set_property (GObject *object,
291 guint prop_id,
292 const GValue *value,
293 GParamSpec *pspec)
294 {
295 IdeToolchain *self = IDE_TOOLCHAIN (object);
296
297 switch (prop_id)
298 {
299 case PROP_ID:
300 ide_toolchain_set_id (self, g_value_get_string (value));
301 break;
302 case PROP_DISPLAY_NAME:
303 ide_toolchain_set_display_name (self, g_value_get_string (value));
304 break;
305 case PROP_HOST_TRIPLET:
306 ide_toolchain_set_host_triplet (self, g_value_get_boxed (value));
307 break;
308 default:
309 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
310 }
311 }
312
313 static void
ide_toolchain_class_init(IdeToolchainClass * klass)314 ide_toolchain_class_init (IdeToolchainClass *klass)
315 {
316 GObjectClass *object_class = G_OBJECT_CLASS (klass);
317
318 object_class->finalize = ide_toolchain_finalize;
319 object_class->get_property = ide_toolchain_get_property;
320 object_class->set_property = ide_toolchain_set_property;
321
322 klass->get_tool_for_language = ide_toolchain_real_get_tool_for_language;
323 klass->get_tools_for_id = ide_toolchain_real_get_tools_for_id;
324
325 properties [PROP_ID] =
326 g_param_spec_string ("id",
327 "Id",
328 "The toolchain identifier",
329 NULL,
330 (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
331
332 properties [PROP_DISPLAY_NAME] =
333 g_param_spec_string ("display-name",
334 "Display Name",
335 "The displayable name of the toolchain",
336 NULL,
337 (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
338
339 properties [PROP_HOST_TRIPLET] =
340 g_param_spec_boxed ("host-triplet",
341 "Host Triplet",
342 "The #IdeTriplet object containing the architecture of the machine on which the compiled binary will run",
343 IDE_TYPE_TRIPLET,
344 (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
345
346 g_object_class_install_properties (object_class, N_PROPS, properties);
347 }
348
349 static void
ide_toolchain_init(IdeToolchain * self)350 ide_toolchain_init (IdeToolchain *self)
351 {
352 IdeToolchainPrivate *priv = ide_toolchain_get_instance_private (self);
353 priv->host_triplet = ide_triplet_new_from_system ();
354 }
355