xref: /openbmc/linux/tools/build/fixdep.c (revision b2441318)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
29f7ef985SJiri Olsa /*
39f7ef985SJiri Olsa  * "Optimize" a list of dependencies as spit out by gcc -MD
49f7ef985SJiri Olsa  * for the build framework.
59f7ef985SJiri Olsa  *
69f7ef985SJiri Olsa  * Original author:
79f7ef985SJiri Olsa  *   Copyright    2002 by Kai Germaschewski  <kai.germaschewski@gmx.de>
89f7ef985SJiri Olsa  *
99f7ef985SJiri Olsa  * This code has been borrowed from kbuild's fixdep (scripts/basic/fixdep.c),
109f7ef985SJiri Olsa  * Please check it for detailed explanation. This fixdep borow only the
119f7ef985SJiri Olsa  * base transformation of dependecies without the CONFIG mangle.
129f7ef985SJiri Olsa  */
139f7ef985SJiri Olsa 
149f7ef985SJiri Olsa #include <sys/types.h>
159f7ef985SJiri Olsa #include <sys/stat.h>
169f7ef985SJiri Olsa #include <sys/mman.h>
179f7ef985SJiri Olsa #include <unistd.h>
189f7ef985SJiri Olsa #include <fcntl.h>
199f7ef985SJiri Olsa #include <string.h>
209f7ef985SJiri Olsa #include <stdlib.h>
219f7ef985SJiri Olsa #include <stdio.h>
229f7ef985SJiri Olsa #include <limits.h>
239f7ef985SJiri Olsa 
249f7ef985SJiri Olsa char *target;
259f7ef985SJiri Olsa char *depfile;
269f7ef985SJiri Olsa char *cmdline;
279f7ef985SJiri Olsa 
usage(void)289f7ef985SJiri Olsa static void usage(void)
299f7ef985SJiri Olsa {
309f7ef985SJiri Olsa 	fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
319f7ef985SJiri Olsa 	exit(1);
329f7ef985SJiri Olsa }
339f7ef985SJiri Olsa 
349f7ef985SJiri Olsa /*
359f7ef985SJiri Olsa  * Print out the commandline prefixed with cmd_<target filename> :=
369f7ef985SJiri Olsa  */
print_cmdline(void)379f7ef985SJiri Olsa static void print_cmdline(void)
389f7ef985SJiri Olsa {
399f7ef985SJiri Olsa 	printf("cmd_%s := %s\n\n", target, cmdline);
409f7ef985SJiri Olsa }
419f7ef985SJiri Olsa 
429f7ef985SJiri Olsa /*
439f7ef985SJiri Olsa  * Important: The below generated source_foo.o and deps_foo.o variable
449f7ef985SJiri Olsa  * assignments are parsed not only by make, but also by the rather simple
459f7ef985SJiri Olsa  * parser in scripts/mod/sumversion.c.
469f7ef985SJiri Olsa  */
parse_dep_file(void * map,size_t len)479f7ef985SJiri Olsa static void parse_dep_file(void *map, size_t len)
489f7ef985SJiri Olsa {
499f7ef985SJiri Olsa 	char *m = map;
509f7ef985SJiri Olsa 	char *end = m + len;
519f7ef985SJiri Olsa 	char *p;
529f7ef985SJiri Olsa 	char s[PATH_MAX];
531cd6472eSJiri Olsa 	int is_target, has_target = 0;
549f7ef985SJiri Olsa 	int saw_any_target = 0;
559f7ef985SJiri Olsa 	int is_first_dep = 0;
569f7ef985SJiri Olsa 
579f7ef985SJiri Olsa 	while (m < end) {
589f7ef985SJiri Olsa 		/* Skip any "white space" */
599f7ef985SJiri Olsa 		while (m < end && (*m == ' ' || *m == '\\' || *m == '\n'))
609f7ef985SJiri Olsa 			m++;
619f7ef985SJiri Olsa 		/* Find next "white space" */
629f7ef985SJiri Olsa 		p = m;
639f7ef985SJiri Olsa 		while (p < end && *p != ' ' && *p != '\\' && *p != '\n')
649f7ef985SJiri Olsa 			p++;
659f7ef985SJiri Olsa 		/* Is the token we found a target name? */
669f7ef985SJiri Olsa 		is_target = (*(p-1) == ':');
679f7ef985SJiri Olsa 		/* Don't write any target names into the dependency file */
689f7ef985SJiri Olsa 		if (is_target) {
699f7ef985SJiri Olsa 			/* The /next/ file is the first dependency */
709f7ef985SJiri Olsa 			is_first_dep = 1;
711cd6472eSJiri Olsa 			has_target = 1;
721cd6472eSJiri Olsa 		} else if (has_target) {
739f7ef985SJiri Olsa 			/* Save this token/filename */
749f7ef985SJiri Olsa 			memcpy(s, m, p-m);
759f7ef985SJiri Olsa 			s[p - m] = 0;
769f7ef985SJiri Olsa 
779f7ef985SJiri Olsa 			/*
789f7ef985SJiri Olsa 			 * Do not list the source file as dependency,
799f7ef985SJiri Olsa 			 * so that kbuild is not confused if a .c file
809f7ef985SJiri Olsa 			 * is rewritten into .S or vice versa. Storing
819f7ef985SJiri Olsa 			 * it in source_* is needed for modpost to
829f7ef985SJiri Olsa 			 * compute srcversions.
839f7ef985SJiri Olsa 			 */
849f7ef985SJiri Olsa 			if (is_first_dep) {
859f7ef985SJiri Olsa 				/*
869f7ef985SJiri Olsa 				 * If processing the concatenation of
879f7ef985SJiri Olsa 				 * multiple dependency files, only
889f7ef985SJiri Olsa 				 * process the first target name, which
899f7ef985SJiri Olsa 				 * will be the original source name,
909f7ef985SJiri Olsa 				 * and ignore any other target names,
919f7ef985SJiri Olsa 				 * which will be intermediate temporary
929f7ef985SJiri Olsa 				 * files.
939f7ef985SJiri Olsa 				 */
949f7ef985SJiri Olsa 				if (!saw_any_target) {
959f7ef985SJiri Olsa 					saw_any_target = 1;
969f7ef985SJiri Olsa 					printf("source_%s := %s\n\n",
979f7ef985SJiri Olsa 						target, s);
989f7ef985SJiri Olsa 					printf("deps_%s := \\\n",
999f7ef985SJiri Olsa 						target);
1009f7ef985SJiri Olsa 				}
1019f7ef985SJiri Olsa 				is_first_dep = 0;
1029f7ef985SJiri Olsa 			} else
1039f7ef985SJiri Olsa 				printf("  %s \\\n", s);
1049f7ef985SJiri Olsa 		}
1059f7ef985SJiri Olsa 		/*
1069f7ef985SJiri Olsa 		 * Start searching for next token immediately after the first
1079f7ef985SJiri Olsa 		 * "whitespace" character that follows this token.
1089f7ef985SJiri Olsa 		 */
1099f7ef985SJiri Olsa 		m = p + 1;
1109f7ef985SJiri Olsa 	}
1119f7ef985SJiri Olsa 
1129f7ef985SJiri Olsa 	if (!saw_any_target) {
1139f7ef985SJiri Olsa 		fprintf(stderr, "fixdep: parse error; no targets found\n");
1149f7ef985SJiri Olsa 		exit(1);
1159f7ef985SJiri Olsa 	}
1169f7ef985SJiri Olsa 
1179f7ef985SJiri Olsa 	printf("\n%s: $(deps_%s)\n\n", target, target);
1189f7ef985SJiri Olsa 	printf("$(deps_%s):\n", target);
1199f7ef985SJiri Olsa }
1209f7ef985SJiri Olsa 
print_deps(void)1219f7ef985SJiri Olsa static void print_deps(void)
1229f7ef985SJiri Olsa {
1239f7ef985SJiri Olsa 	struct stat st;
1249f7ef985SJiri Olsa 	int fd;
1259f7ef985SJiri Olsa 	void *map;
1269f7ef985SJiri Olsa 
1279f7ef985SJiri Olsa 	fd = open(depfile, O_RDONLY);
1289f7ef985SJiri Olsa 	if (fd < 0) {
1299f7ef985SJiri Olsa 		fprintf(stderr, "fixdep: error opening depfile: ");
1309f7ef985SJiri Olsa 		perror(depfile);
1319f7ef985SJiri Olsa 		exit(2);
1329f7ef985SJiri Olsa 	}
1339f7ef985SJiri Olsa 	if (fstat(fd, &st) < 0) {
1349f7ef985SJiri Olsa 		fprintf(stderr, "fixdep: error fstat'ing depfile: ");
1359f7ef985SJiri Olsa 		perror(depfile);
1369f7ef985SJiri Olsa 		exit(2);
1379f7ef985SJiri Olsa 	}
1389f7ef985SJiri Olsa 	if (st.st_size == 0) {
1399f7ef985SJiri Olsa 		fprintf(stderr, "fixdep: %s is empty\n", depfile);
1409f7ef985SJiri Olsa 		close(fd);
1419f7ef985SJiri Olsa 		return;
1429f7ef985SJiri Olsa 	}
1439f7ef985SJiri Olsa 	map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1449f7ef985SJiri Olsa 	if ((long) map == -1) {
1459f7ef985SJiri Olsa 		perror("fixdep: mmap");
1469f7ef985SJiri Olsa 		close(fd);
1479f7ef985SJiri Olsa 		return;
1489f7ef985SJiri Olsa 	}
1499f7ef985SJiri Olsa 
1509f7ef985SJiri Olsa 	parse_dep_file(map, st.st_size);
1519f7ef985SJiri Olsa 
1529f7ef985SJiri Olsa 	munmap(map, st.st_size);
1539f7ef985SJiri Olsa 
1549f7ef985SJiri Olsa 	close(fd);
1559f7ef985SJiri Olsa }
1569f7ef985SJiri Olsa 
main(int argc,char ** argv)1579f7ef985SJiri Olsa int main(int argc, char **argv)
1589f7ef985SJiri Olsa {
1599f7ef985SJiri Olsa 	if (argc != 4)
1609f7ef985SJiri Olsa 		usage();
1619f7ef985SJiri Olsa 
1629f7ef985SJiri Olsa 	depfile = argv[1];
1639f7ef985SJiri Olsa 	target  = argv[2];
1649f7ef985SJiri Olsa 	cmdline = argv[3];
1659f7ef985SJiri Olsa 
1669f7ef985SJiri Olsa 	print_cmdline();
1679f7ef985SJiri Olsa 	print_deps();
1689f7ef985SJiri Olsa 
1699f7ef985SJiri Olsa 	return 0;
1709f7ef985SJiri Olsa }
171