Polishing makefile
[squish.git] / make_squishy
blob098eeca3d2a2abeb275247bb0d6f60d6d2ff473a
1 #!/usr/bin/env lua
3 if not arg[1] or arg[1]:match("%-%-?help") or arg[1]:match("^[/-]%?$") then
4         print "make_squishy - Generate squishy files for your projects"
5         print ""
6         print(" Usage: "..arg[0].." FILE1 FILE2 FILE...");
7         print ""
8         print "make_squishy will scan the given files for require() calls, and convert the "
9         print "found modules into a squishy file, 'squishy.new'. make_squishy automatically scans "
10         print "the modules it finds, looking for further dependencies. To disable this, use "
11         print "the --no-recursion option."
12         return;
13 end
16 local short_opts = { v = "verbose", vv = "very_verbose", o = "output", q = "quiet", qq = "very_quiet" }
17 local files, opts = {}, {};
18 local scanned_files, modules = {}, {};
20 for _, opt in ipairs(arg) do
21         if opt:match("^%-") then
22                 local name = opt:match("^%-%-?([^%s=]+)()")
23                 name = (short_opts[name] or name):gsub("%-+", "_");
24                 if name:match("^no_") then
25                         name = name:sub(4, -1);
26                         opts[name] = false;
27                 else
28                         opts[name] = opt:match("=(.*)$") or true;
29                 end
30         else
31                 table.insert(files, opt);
32         end
33 end
35 if opts.very_verbose then opts.verbose = true; end
36 if opts.very_quiet then opts.quiet = true; end
38 local noprint = function () end
39 local print_err, print_info, print_verbose, print_debug = noprint, noprint, noprint, noprint;
41 if not opts.very_quiet then print_err = print; end
42 if not opts.quiet then print_info = print; end
43 if opts.verbose or opts.very_verbose then print_verbose = print; end
44 if opts.very_verbose then print_debug = print; end
46 local squishy = io.stdout
48 local LUA_DIRSEP = package.config:sub(1,1);
49 local LUA_PATH_MARK = package.config:sub(5,5);
51 local base_path = (files[1]:match("^(.-)"..LUA_DIRSEP.."[^"..LUA_DIRSEP.."]*$") or ".").."/";
53 local package_path = package.path:gsub("[^;]+", function (path)
54                 if not path:match("^%"..LUA_DIRSEP) then
55                         return base_path..path;
56                 end
57         end):gsub("/%./", "/");
58 local package_cpath = package.cpath:gsub("[^;]+", function (path)
59                 if not path:match("^%"..LUA_DIRSEP) then
60                         return base_path..path;
61                 end
62         end):gsub("/%./", "/");
65 function scan_file(outfile, scanfile)
66         for line in io.lines(scanfile) do
67                 for _, module in (" "..line):gmatch("[^%w_]require%s*%(?([\"'])(.-)%1") do
68                         if not modules[module] then
69                                 local binary;
70                                 modules[module] = true;
71                                 local filename = resolve_module(module, package_path);
72                                 if false and not filename then
73                                         binary = true;
74                                         filename = resolve_module(module, package_cpath);
75                                 end
76                                 if not filename then
77                                         print_info("Couldn't resolve module '"..module.."' to a file (required in "..scanfile..")");
78                                 elseif opts.recursion ~= false and not scanned_files[filename] then
79                                         scanned_files[filename] = true;
80                                         table.insert(files, filename);
81                                 end
82                                 if filename then
83                                         outfile:write((binary and "Binary" or ""), string.format([[Module %q %q]], module, filename:gsub("^"..base_path:gsub("%p", "%%%1"), "")), "\n");
84                                 end
85                         end
86                 end
87         end
88 end
91 function resolve_module(name, path)
92         name = name:gsub("%.", LUA_DIRSEP);
93         for c in path:gmatch("[^;]+") do
94                 c = c:gsub("%"..LUA_PATH_MARK, name);
95                 print_debug("Testing: "..c)
96                 local f = io.open(c);
97                 if f then
98                         f:close();
99                         return c;
100                 end
101         end
102         return nil; -- not found
105 for _, filename in ipairs(files) do
106         squishy:write(string.format([[Main %q]], filename:gsub("^"..base_path:gsub("%p", "%%%1"), "")), "\n");
108 squishy:write("\n");
109 for _, filename in ipairs(files) do
110         scanned_files[filename] = true;
111         print_verbose("Found:", filename);
112         scan_file(squishy, filename)