]>
Commit | Line | Data |
---|---|---|
1a276007 MT |
1 | /*############################################################################# |
2 | # # | |
3 | # Pakfire - The IPFire package management system # | |
4 | # Copyright (C) 2021 Pakfire development team # | |
5 | # # | |
6 | # This program is free software: you can redistribute it and/or modify # | |
7 | # it under the terms of the GNU General Public License as published by # | |
8 | # the Free Software Foundation, either version 3 of the License, or # | |
9 | # (at your option) any later version. # | |
10 | # # | |
11 | # This program is distributed in the hope that it will be useful, # | |
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
14 | # GNU General Public License for more details. # | |
15 | # # | |
16 | # You should have received a copy of the GNU General Public License # | |
17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
18 | # # | |
19 | #############################################################################*/ | |
20 | ||
21 | #include <errno.h> | |
22 | #include <stdlib.h> | |
23 | ||
24 | #include <pakfire/build.h> | |
25 | #include <pakfire/execute.h> | |
26 | #include <pakfire/dist.h> | |
27 | #include <pakfire/logging.h> | |
28 | #include <pakfire/parser.h> | |
29 | #include <pakfire/private.h> | |
30 | #include <pakfire/types.h> | |
31 | #include <pakfire/util.h> | |
32 | ||
33 | static const char* stages[] = { | |
34 | "prepare", | |
35 | "build", | |
36 | "test", | |
37 | "install", | |
38 | NULL, | |
39 | }; | |
40 | ||
41 | #define TEMPLATE \ | |
42 | "#!/bin/bash --login\n" \ | |
43 | "\n" \ | |
44 | "set -e\n" \ | |
45 | "set -x\n" \ | |
46 | "\n" \ | |
47 | "%%{_%s}\n" \ | |
48 | "\n" \ | |
49 | "exit 0\n" | |
50 | ||
a50bde9c MT |
51 | static int pakfire_build_package(Pakfire pakfire, PakfireParser makefile, const char* handle) { |
52 | int r = 1; | |
53 | ||
54 | // Expand the handle into the package name | |
55 | char* name = pakfire_parser_expand(makefile, "packages", handle); | |
56 | if (!name) { | |
57 | ERROR(pakfire, "Could not get package name: %s\n", strerror(errno)); | |
58 | goto ERROR; | |
59 | } | |
60 | ||
61 | INFO(pakfire, "Building package '%s'...\n", name); | |
62 | ||
63 | // XXX actually do all the work | |
64 | ||
65 | // Success | |
66 | r = 0; | |
67 | ||
68 | ERROR: | |
69 | if (name) | |
70 | free(name); | |
71 | ||
72 | return r; | |
73 | } | |
74 | ||
75 | static int pakfire_build_packages(Pakfire pakfire, PakfireParser makefile) { | |
76 | DEBUG(pakfire, "Creating packages..."); | |
77 | int r = 1; | |
78 | ||
79 | // Fetch a list all all packages | |
80 | char** packages = pakfire_parser_list_namespaces(makefile, "packages.package:*"); | |
81 | if (!packages) { | |
82 | ERROR(pakfire, "Could not find any packages: %s\n", strerror(errno)); | |
83 | goto ERROR; | |
84 | } | |
85 | ||
86 | unsigned int num_packages = 0; | |
87 | ||
88 | // Count how many packages we have | |
89 | for (char** package = packages; *package; package++) | |
90 | num_packages++; | |
91 | ||
92 | DEBUG(pakfire, "Found %d package(s)\n", num_packages); | |
93 | ||
94 | // Build packages in reverse order | |
95 | for (int i = num_packages - 1; i >= 0; i--) { | |
96 | r = pakfire_build_package(pakfire, makefile, | |
97 | packages[i] + strlen("packages.package:")); | |
98 | if (r) | |
99 | goto ERROR; | |
100 | } | |
101 | ||
102 | // Success | |
103 | r = 0; | |
104 | ||
105 | ERROR: | |
106 | if (packages) | |
107 | free(packages); | |
108 | ||
109 | return r; | |
110 | } | |
111 | ||
7d999600 MT |
112 | static int pakfire_build_stage(Pakfire pakfire, PakfireParser makefile, const char* stage, |
113 | pakfire_execute_logging_callback logging_callback, void* data) { | |
1a276007 MT |
114 | char template[1024]; |
115 | ||
116 | // Prepare template for this stage | |
117 | int r = pakfire_string_format(template, TEMPLATE, stage); | |
118 | if (r < 0) | |
119 | return r; | |
120 | ||
121 | // Create the build script | |
122 | char* script = pakfire_parser_expand(makefile, "build", template); | |
123 | if (!script) { | |
124 | ERROR(pakfire, "Could not generate the build script for stage '%s': %s\n", | |
125 | stage, strerror(errno)); | |
126 | goto ERROR; | |
127 | } | |
128 | ||
129 | INFO(pakfire, "Running build stage '%s'\n", stage); | |
130 | ||
7d999600 MT |
131 | r = pakfire_execute_script(pakfire, script, strlen(script), NULL, 0, |
132 | logging_callback, data); | |
1a276007 MT |
133 | if (r) { |
134 | ERROR(pakfire, "Build stage '%s' failed with status %d\n", stage, r); | |
135 | } | |
136 | ||
137 | ERROR: | |
138 | if (script) | |
139 | free(script); | |
140 | ||
141 | return r; | |
142 | } | |
143 | ||
144 | PAKFIRE_EXPORT int pakfire_build(Pakfire pakfire, const char* path, | |
7d999600 MT |
145 | const char* target, int flags, |
146 | pakfire_execute_logging_callback logging_callback, void* data) { | |
1a276007 MT |
147 | PakfireParser makefile = NULL; |
148 | struct pakfire_parser_error* error = NULL; | |
149 | ||
150 | // Read makefile | |
151 | int r = pakfire_read_makefile(&makefile, pakfire, path, &error); | |
152 | if (r) { | |
153 | if (error) { | |
154 | ERROR(pakfire, "Could not parse makefile %s: %s\n", path, | |
155 | pakfire_parser_error_get_message(error)); | |
156 | pakfire_parser_error_unref(error); | |
157 | } else { | |
158 | ERROR(pakfire, "Could not parse makefile %s: %s\n", path, | |
159 | strerror(errno)); | |
160 | } | |
161 | ||
162 | goto ERROR; | |
163 | } | |
164 | ||
165 | // Run through all build stages | |
166 | for (const char** stage = stages; *stage; stage++) { | |
7d999600 | 167 | int r = pakfire_build_stage(pakfire, makefile, *stage, logging_callback, data); |
1a276007 MT |
168 | if (r) { |
169 | // Drop to a shell for debugging | |
170 | if (flags & PAKFIRE_BUILD_INTERACTIVE) | |
171 | pakfire_shell(pakfire); | |
172 | ||
173 | goto ERROR; | |
174 | } | |
175 | } | |
176 | ||
a50bde9c MT |
177 | // Create the packages |
178 | r = pakfire_build_packages(pakfire, makefile); | |
179 | if (r) { | |
180 | ERROR(pakfire, "Could not create packages: %s\n", strerror(errno)); | |
181 | goto ERROR; | |
182 | } | |
1a276007 MT |
183 | |
184 | ERROR: | |
185 | if (makefile) | |
186 | pakfire_parser_unref(makefile); | |
187 | ||
188 | return r; | |
189 | } | |
190 | ||
191 | PAKFIRE_EXPORT int pakfire_shell(Pakfire pakfire) { | |
192 | const char* argv[] = { | |
193 | "/bin/bash", "--login", NULL, | |
194 | }; | |
195 | ||
196 | const int flags = | |
197 | PAKFIRE_EXECUTE_INTERACTIVE | PAKFIRE_EXECUTE_ENABLE_NETWORK; | |
198 | ||
199 | return pakfire_execute(pakfire, argv, NULL, flags, NULL, NULL); | |
200 | } |