1 /*#############################################################################
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2023 Pakfire development team #
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. #
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. #
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/>. #
19 #############################################################################*/
24 #include <sys/syslog.h>
31 #include <pakfire/archive.h>
32 #include <pakfire/build.h>
33 #include <pakfire/log_file.h>
34 #include <pakfire/package.h>
35 #include <pakfire/root.h>
36 #include <pakfire/path.h>
37 #include <pakfire/repo.h>
39 #define MAX_MAKEFILES 32
41 struct cli_local_args
{
45 BUILD_INTERACTIVE
= (1 << 0),
46 BUILD_ENABLE_CCACHE
= (1 << 1),
47 BUILD_ENABLE_SNAPSHOT
= (1 << 2),
48 BUILD_ENABLE_TESTS
= (1 << 3),
52 pakfire_log_file
* log_file
;
56 char* makefiles
[MAX_MAKEFILES
];
57 unsigned int num_makefiles
;
61 OPT_DISABLE_CCACHE
= 1,
62 OPT_DISABLE_SNAPSHOT
= 2,
63 OPT_DISABLE_TESTS
= 3,
65 OPT_NON_INTERACTIVE
= 5,
69 static struct argp_option options
[] = {
70 { "disable-ccache", OPT_DISABLE_CCACHE
, NULL
, 0, "Disable the ccache", 0 },
71 { "disable-snapshot", OPT_DISABLE_SNAPSHOT
, NULL
, 0, "Do not use the snapshot", 0 },
72 { "disable-tests", OPT_DISABLE_TESTS
, NULL
, 0, "Do not run tests", 0 },
73 { "log-file", OPT_LOG_FILE
, "PATH", 0, "Writes the log to a file", 0 },
74 { "non-interactive", OPT_NON_INTERACTIVE
, NULL
, 0, "Run the build non-interactively", 0 },
75 { "target", OPT_TARGET
, "TARGET", 0, "Output all packages into this directory", 0 },
79 static error_t
parse(int key
, char* arg
, struct argp_state
* state
, void* data
) {
80 struct cli_local_args
* args
= data
;
83 case OPT_DISABLE_CCACHE
:
84 args
->flags
&= ~BUILD_ENABLE_CCACHE
;
87 case OPT_DISABLE_SNAPSHOT
:
88 args
->flags
&= ~BUILD_ENABLE_SNAPSHOT
;
91 case OPT_DISABLE_TESTS
:
92 args
->flags
&= ~BUILD_ENABLE_TESTS
;
99 case OPT_NON_INTERACTIVE
:
100 args
->flags
&= ~BUILD_INTERACTIVE
;
108 if (args
->num_makefiles
>= MAX_MAKEFILES
)
111 args
->makefiles
[args
->num_makefiles
++] = arg
;
115 return ARGP_ERR_UNKNOWN
;
121 static void log_callback(void* data
, int priority
, const char* file
, int line
,
122 const char* function
, const char* format
, va_list args
)
123 __attribute__((format(printf
, 6, 0)));
125 static void log_callback(void* data
, int priority
, const char* file
, int line
,
126 const char* function
, const char* format
, va_list args
) {
127 const struct cli_local_args
* local_args
= data
;
132 length
= vasprintf(&buffer
, format
, args
);
137 // Highlight any warnings
139 fputs(color_yellow(), stderr
);
140 fprintf(stderr
, "%s", buffer
);
141 fputs(color_reset(), stderr
);
144 // Highlight any error messages
146 fputs(color_highlight(), stderr
);
147 fprintf(stderr
, "%s", buffer
);
148 fputs(color_reset(), stderr
);
151 // Print anything to standard output
153 fprintf(stdout
, "%s", buffer
);
157 // Write to the log file
158 if (local_args
->log_file
)
159 pakfire_log_file_write(local_args
->log_file
, priority
, buffer
, length
);
165 static int result_callback(pakfire_ctx
* ctx
, pakfire_root
* root
,
166 pakfire_build
* build
, pakfire_archive
* archive
, void* data
) {
167 const struct cli_local_args
* local_args
= data
;
168 pakfire_package
* pkg
= NULL
;
169 pakfire_repo
* local
= NULL
;
173 // Fetch the package metadata
174 r
= pakfire_archive_make_package(archive
, NULL
, &pkg
);
179 const char* nevra
= pakfire_package_get_string(pkg
, PAKFIRE_PKG_NEVRA
);
181 // Fetch the local repository & import the archive
182 local
= pakfire_root_get_repo(root
, PAKFIRE_REPO_LOCAL
);
184 r
= pakfire_repo_import_archive(local
, archive
, NULL
);
186 ERROR(ctx
, "Could not import %s to the local repository: %s\n",
187 nevra
, strerror(-r
));
192 // Copy to the target (if given)
193 if (local_args
->target
) {
194 // Fetch the filename
195 const char* filename
= pakfire_package_get_filename(pkg
);
197 // Make the absolute target path
198 r
= pakfire_path_append(path
, local_args
->target
, filename
);
202 // Copy (or link) the package to the target path
203 r
= pakfire_archive_link_or_copy(archive
, path
);
205 ERROR(ctx
, "Could not copy %s to %s: %s\n",
206 nevra
, path
, strerror(-r
));
213 pakfire_repo_unref(local
);
215 pakfire_package_unref(pkg
);
220 int cli_build(void* data
, int argc
, char* argv
[]) {
221 struct cli_global_args
* global_args
= data
;
222 struct cli_local_args local_args
= {
225 BUILD_ENABLE_CCACHE
|
226 BUILD_ENABLE_SNAPSHOT
|
229 pakfire_build
* build
= NULL
;
230 int flags
= PAKFIRE_BUILD_LOCAL
;
233 // Parse the command line
234 r
= cli_parse(options
, NULL
, NULL
, NULL
, parse
, 0, argc
, argv
, &local_args
);
238 // Replace the logger
239 pakfire_ctx_set_log_callback(global_args
->ctx
, log_callback
, &local_args
);
242 if (local_args
.flags
& BUILD_ENABLE_SNAPSHOT
)
243 flags
|= PAKFIRE_BUILD_ENABLE_SNAPSHOT
;
245 // Is the build interactive?
246 if (local_args
.flags
& BUILD_INTERACTIVE
)
247 flags
|= PAKFIRE_BUILD_INTERACTIVE
;
250 if (!(local_args
.flags
& BUILD_ENABLE_CCACHE
))
251 flags
|= PAKFIRE_BUILD_DISABLE_CCACHE
;
254 if (!(local_args
.flags
& BUILD_ENABLE_TESTS
))
255 flags
|= PAKFIRE_BUILD_DISABLE_TESTS
;
257 // Create the log file
258 if (local_args
.log_path
) {
259 r
= pakfire_log_file_create(&local_args
.log_file
,
260 global_args
->ctx
, local_args
.log_path
, NULL
, 0);
265 // Setup the build environment
266 r
= cli_setup_build(&build
, global_args
, flags
);
270 // Process all packages
271 for (unsigned int i
= 0; i
< local_args
.num_makefiles
; i
++) {
273 r
= pakfire_build_exec(build
, local_args
.makefiles
[i
], result_callback
, &local_args
);
275 fprintf(stderr
, "Could not build %s\n", local_args
.makefiles
[i
]);
281 if (local_args
.log_file
)
282 pakfire_log_file_unref(local_args
.log_file
);
284 pakfire_build_unref(build
);