owwwo
This commit is contained in:
commit
c7d30722bb
4 changed files with 282 additions and 0 deletions
25
LICENSE.txt
Normal file
25
LICENSE.txt
Normal file
|
@ -0,0 +1,25 @@
|
|||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
|
50
README.md
Normal file
50
README.md
Normal file
|
@ -0,0 +1,50 @@
|
|||
# what??
|
||||
|
||||
its a c build system. it is not the fastest nor the most extensible but damn me if it aint easy to use pardner.
|
||||
|
||||
please do not use this for any serious projects
|
||||
|
||||
# installation
|
||||
|
||||
```
|
||||
chmod +x install.sh
|
||||
./install.sh
|
||||
```
|
||||
|
||||
or, if you want to use luajit:
|
||||
|
||||
```
|
||||
./install.sh -luajit
|
||||
```
|
||||
|
||||
depends on [luafilesystem](https://keplerproject.github.io/luafilesystem/) or [lua filesystem ffi](https://github.com/spacewander/luafilesystem) if using luajit
|
||||
|
||||
# usage
|
||||
|
||||
`lcmk` will look for a file `build.lua` in your current directory and execute. this file may define the following global variables:
|
||||
* `PROG` program name (for compilation output). REQUIRED
|
||||
* `SRC` table containing source file paths (.c and .cpp); do not define or set to "\*.c" to let `lcmk` find them by itself
|
||||
* `CC` the C compiler.
|
||||
* `CFLAGS` string containing flags to be passed to the compiler
|
||||
* `LINK` string containing libraries to link against
|
||||
any of these variables might be provided through environment variables instead
|
||||
|
||||
then, you can invoke the program with `lcmk [options]`
|
||||
|
||||
options is an arbitrary list of strings stored in global table `opt` that the build file might use to change something in the build.
|
||||
the clean option is builtin and will remove all \*.o files along with $PROG
|
||||
|
||||
an example build file could be:
|
||||
|
||||
```lua
|
||||
SRC = {"main.c", "foo.c"}
|
||||
PROG = "./foo"
|
||||
CFLAGS = "-Wall"
|
||||
LINK = "-lm"
|
||||
|
||||
if opt.debug then
|
||||
CFLAGS = CFLAGS .. " -ggdb"
|
||||
end
|
||||
```
|
||||
|
||||
`lcmk` will handle everything else (object files, dependencies, etc)
|
20
install.sh
Executable file
20
install.sh
Executable file
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
DEST=/usr/bin/
|
||||
|
||||
LUA="/bin/env lua"
|
||||
if [ "$1" == "-h" ]; then
|
||||
echo "usage:"
|
||||
echo " $0 [options]"
|
||||
echo "options: "
|
||||
echo " -luajit: install using luajit (needs lfs_ffi: https://github.com/spacewander/luafilesystem)"
|
||||
exit
|
||||
elif [ "$1" == "-luajit" ]; then
|
||||
LUA="/bin/env luajit"
|
||||
fi
|
||||
|
||||
echo "#!/bin/sh" > lcmk
|
||||
echo "$LUA `pwd`/lcmk.lua $@" >> lcmk
|
||||
chmod +x lcmk
|
||||
|
||||
mv lcmk "$DEST"
|
187
lcmk.lua
Normal file
187
lcmk.lua
Normal file
|
@ -0,0 +1,187 @@
|
|||
local lfs = require(jit and 'lfs_ffi' or 'lfs')
|
||||
local inspect
|
||||
function inspect(t,s)
|
||||
s = s or ""
|
||||
r = ""
|
||||
for k,v in pairs(t) do
|
||||
r = r..(s..k..": "..(type(v) == "table" and "\n"..inspect(v,s.." ") or tostring(v).."\n"))
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
local path = lfs.currentdir() .. "/build.lua"
|
||||
|
||||
local buildf = loadfile(path)
|
||||
if not buildf then
|
||||
error "no build file"
|
||||
end
|
||||
|
||||
local function initvar(name, default)
|
||||
_G[name] = os.getenv(name) or default or ""
|
||||
end
|
||||
|
||||
initvar("CC", "gcc")
|
||||
initvar("CFLAGS")
|
||||
initvar("LINK")
|
||||
initvar("SRC", "*.c")
|
||||
|
||||
opt = {}
|
||||
|
||||
for _,arg in ipairs(arg) do
|
||||
opt[arg] = true
|
||||
end
|
||||
|
||||
function buildobj(o)
|
||||
local cmd = ("%s %s %s -c -o %s %s"):format(CC, CFLAGS, LINK, o.out, o.src)
|
||||
print("BUILDING OBJECT:\n"..cmd)
|
||||
os.execute(cmd)
|
||||
end
|
||||
|
||||
function buildprog()
|
||||
local objs = ""
|
||||
for _,o in ipairs(OBJ) do
|
||||
objs = objs..o.path.." "
|
||||
end
|
||||
local cmd = ("%s %s %s -o %s %s"):format(CC, CFLAGS, LINK, PROG, objs)
|
||||
print("BUILDING PROGRAM:\n"..cmd)
|
||||
os.execute(cmd)
|
||||
end
|
||||
|
||||
buildf()
|
||||
|
||||
if not PROG then
|
||||
error "must provide 'PROG'"
|
||||
end
|
||||
|
||||
function issourcefile(f)
|
||||
return f:sub(#f-1,#f) == ".c" or f:sub(#f-3,#f) == ".cpp"
|
||||
end
|
||||
|
||||
local function concat(dir,file) --concats directory name + filename
|
||||
if not dir or dir == lfs.currentdir() then
|
||||
return file
|
||||
else
|
||||
|
||||
return ({(dir .. "/" .. file)
|
||||
:gsub("[^/]*/../", "") --remove redundant expressions as in "foo/../bar" -> "bar"
|
||||
})[1]
|
||||
end
|
||||
end
|
||||
|
||||
if SRC =="*.c" then
|
||||
SRC = {}
|
||||
local find
|
||||
function find(dir)
|
||||
--print("searching in "..dir)
|
||||
for f,_ in lfs.dir(dir) do
|
||||
local attr = lfs.attributes(concat(dir,f))
|
||||
if attr and (attr.mode == "file" or attr.mode == "link") and issourcefile(f) then
|
||||
table.insert(SRC, concat(dir,f))
|
||||
elseif attr and attr.mode == "directory" and f ~= "." and f ~= ".." and f ~= ".git" then
|
||||
find(concat(dir,f)) --recursive
|
||||
end
|
||||
end
|
||||
end
|
||||
find(lfs.currentdir())
|
||||
end
|
||||
|
||||
if _SHOWSRC then
|
||||
print(inspect(SRC))
|
||||
end
|
||||
|
||||
function getdeps(p, exclude)
|
||||
--print(p)
|
||||
local f = io.open(p)
|
||||
if not f then
|
||||
return nil
|
||||
end
|
||||
|
||||
exclude = exclude or {}
|
||||
for k,v in ipairs(exclude) do exclude[v] = true end
|
||||
local deps = {}
|
||||
|
||||
local _,_,dir = p:find("(.*)/.*$")
|
||||
|
||||
for l in f:lines() do
|
||||
local _,_,s = l:find('%s*#include%s*\"(.*)\"')
|
||||
if s then
|
||||
s = concat(dir,s)
|
||||
print(s)
|
||||
local dep2 = getdeps(s, deps)
|
||||
if not exclude[s] then
|
||||
for k,v in ipairs(dep2) do
|
||||
table.insert(deps, v)
|
||||
end
|
||||
table.insert(deps,s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for k,v in pairs(deps) do
|
||||
if type(k) == "string" then
|
||||
deps[k] = nil
|
||||
end
|
||||
end
|
||||
return deps
|
||||
end
|
||||
|
||||
OBJ = {}
|
||||
|
||||
for k,v in ipairs(SRC) do
|
||||
OBJ[k] = {
|
||||
path = v:gsub("%.cp?p?$", ".o"),
|
||||
deps = getdeps(v),
|
||||
src = v
|
||||
}
|
||||
table.insert(OBJ[k].deps, v)
|
||||
end
|
||||
|
||||
if _SHOWOBJ then
|
||||
print(inspect(OBJ))
|
||||
end
|
||||
|
||||
if opt.clean then
|
||||
local objs = ""
|
||||
for _,o in ipairs(OBJ) do
|
||||
objs = objs..o.path.." "
|
||||
end
|
||||
|
||||
local cmd = ("rm %s %s"):format(objs, PROG)
|
||||
print("CLEANING: "..cmd)
|
||||
return os.execute(cmd)
|
||||
end
|
||||
|
||||
local tobuild = {}
|
||||
|
||||
for _,o in ipairs(OBJ) do
|
||||
local attr = lfs.attributes(o.path)
|
||||
if not attr then
|
||||
table.insert(tobuild, {src = o.src, out = o.path})
|
||||
else
|
||||
local o_mod = attr.modification
|
||||
for _,dep in ipairs(o.deps) do
|
||||
local d_mod = lfs.attributes(dep).modification
|
||||
--print(o_mod-d_mod)
|
||||
if d_mod > o_mod then
|
||||
--dependency is newer: rebuild
|
||||
table.insert(tobuild, {src = o.src, out = o.path})
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #tobuild < 1 then
|
||||
print "nothing to do"
|
||||
return 0
|
||||
end
|
||||
|
||||
if _SHOWBUILD then
|
||||
print(inspect(tobuild))
|
||||
end
|
||||
|
||||
for _,o in ipairs(tobuild) do
|
||||
buildobj(o)
|
||||
end
|
||||
|
||||
buildprog()
|
Loading…
Reference in a new issue