summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkennyballou <kballou@onyx.boisestate.edu>2013-01-21 18:16:57 -0700
committerkennyballou <kballou@onyx.boisestate.edu>2013-01-21 18:16:57 -0700
commit170d169baff41b5643650f79ddc8209dae6dce6c (patch)
tree1b1a01fd479c844e6a181ccac3b37314e71d6760
parent9b7f8a34ae8a79ec4b099140a7536976cf6a510e (diff)
parent14f2fef895ce38c53bbe629fd2449ba02c9dac07 (diff)
downloadxnt-170d169baff41b5643650f79ddc8209dae6dce6c.tar.gz
xnt-170d169baff41b5643650f79ddc8209dae6dce6c.tar.xz
Merge branch 'refactor_build_modules'
Conflicts: .gitignore
-rw-r--r--.gitignore1
-rw-r--r--README14
-rw-r--r--docs/source/buildreference.rst110
-rw-r--r--docs/source/index.rst1
-rw-r--r--docs/source/taskreference.rst28
-rw-r--r--xnt/build/ant.py30
-rw-r--r--xnt/build/cc.py73
-rw-r--r--xnt/build/make.py17
-rw-r--r--xnt/build/nant.py30
-rw-r--r--xnt/tests/compilercollectiontests.py121
10 files changed, 328 insertions, 97 deletions
diff --git a/.gitignore b/.gitignore
index 3c4a3b2..a858bbc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,5 @@
dist
**MANIFEST
bin
+docs/build
Xnt.egg-info
diff --git a/README b/README
index c8a43d0..f925344 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-.. # vim: set colorcolumn=70:textwidth=69
+.. # vim: colorcolumn=70:textwidth=69:syntax=rst:
===
Xnt
@@ -106,7 +106,7 @@ PyPi/ Pip
To install from PyPi_, you will need `pip`_. Once you have ``pip``,
you may only run::
- $ pip install Xnt [--user]
+ $ pip[2] install Xnt [--user]
Linux/ Unix
-----------
@@ -133,7 +133,7 @@ Here is a simple ``build.py``::
from xnt import target
from xnt.tasks import *
- from xnt.builders import ant
+ from xnt.build import make
@target
def init():
@@ -142,7 +142,7 @@ Here is a simple ``build.py``::
@target
def build():
init()
- ant("build")
+ make.ant("build")
@target
def clean():
@@ -187,9 +187,9 @@ or:
* Nothing; if no target is specified, Xnt will attempt to invoke the
``default`` target
-* ``help``: if this 'special' target is provided, Xnt will print all
- targets marked by the ``@target`` decorator and possibly their
- docstrings if they are defined
+* ``list-targets``: if this 'special' target is provided, Xnt will
+ print all targets marked by the ``@target`` decorator and possibly
+ their docstrings if they are defined
For more information about Xnt and the build in functions, see the
`Package Documentation`_.
diff --git a/docs/source/buildreference.rst b/docs/source/buildreference.rst
new file mode 100644
index 0000000..704c812
--- /dev/null
+++ b/docs/source/buildreference.rst
@@ -0,0 +1,110 @@
+===============
+Build Reference
+===============
+
+Xnt has several "build" modules to aid you in your compliation and project/
+sub-project build steps
+
+Overview
+========
+
+* `Make`_
+
+* `Compiler Collection`_
+
+Make
+====
+
+Apache Ant
+----------
+
+.. _xnt.build.make.ant:
+.. function:: ant(path="", target="")
+
+ Invoke Apache Ant in either the current working directory or the specified
+ directory using the empty (default) target or the specified target.
+
+Gnu Make
+--------
+
+.. _xnt.bulid.make.make:
+.. function:: make(path="", target="")
+
+ Invoke Gnu Make (*make*) in either the current working directory or the
+ specified directory using the empty (default) target or the specified
+ target.
+
+(.NET)Ant
+---------
+
+.. _xnt.build.make.nant:
+.. function:: nant(path="", target="")
+
+ Invoke NAnt in either the current working directory or the specified
+ directory using the empty (default) target or the specified target.
+
+Compiler Collection
+===================
+
+For all compilers so far, Xnt assumes they are installed and in your `$PATH`.
+If they are not, an error will be thrown (by subprocess)
+
+gcc/g++
+-------
+
+.. _xnt.build.cc.gcc:
+.. function:: gcc(src, flags=[])
+
+ Compile `src` with the `gcc` to the default `out` (:ref:`defaultOut`) of
+ that source. Passing `flags` as given.
+
+.. _xnt.build.cc.gcc_o:
+.. function:: gcc_o(src, o, flags=[])
+
+ Compile `src` with `gcc` to the out file specified by `o`. Passing `flags`
+ as given.
+
+.. _xnt.build.cc.gpp:
+.. function:: gpp(src, flags=[])
+
+ Compile `src` with `g++` to the default `out` (:ref:`defaultOut`) of that
+ source. Passing `flags` as given.
+
+.. _xnt.bulid.cc.gpp_o:
+.. function:: gpp_o(src, o, flags=[])
+
+ Compile `src` with `g++` to the out file specified by `o`. Passing `flags`
+ as given.
+
+Javac
+-----
+
+.. _xnt.build.cc.javac:
+.. function:: javac(src, flags=[])
+
+ Compile `src` with `javac` to the default out file for the source. Passing
+ `flags` as given.
+
+Notes
+-----
+
+.. _defaultOut:
+
+Default out
+~~~~~~~~~~~
+
+Most, if not all, compilers have a default name given to compiled binaries when
+no output file name is given. For example, `gcc` will give code with a `main`
+method a name of `a.out` or `%.o` for objects, and so on. `javac` defaults to
+`<class-name>.class`.
+
+.. _recompile:
+
+Recompile
+~~~~~~~~~
+
+At the current moment, all compile wrappers do not do "smart" checks for
+compilation. That is, *all* compile steps will `rebuild` regardless if the
+binary file is modified later than the source file. This would be a nice
+feature, but I fear it would be too expensive (complicated) and out of the
+scope of this project to implement correctly.
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 6ebb18e..6e1462c 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -28,6 +28,7 @@ Contents:
buildfile
taskreference
+ buildreference
Motivation
==========
diff --git a/docs/source/taskreference.rst b/docs/source/taskreference.rst
index c303b5f..1c5fbe8 100644
--- a/docs/source/taskreference.rst
+++ b/docs/source/taskreference.rst
@@ -114,34 +114,6 @@ Compile Tasks
Invoke Python setup.py given the list of *commands* (or options) in the
current directory or in a different directory, specified by *dir*.
-Apache Ant
-----------
-
-.. _xnt.build.ant.ant:
-.. function:: ant(path="", target="")
-
- Invoke Apache Ant in either the current working directory or the specified
- directory using the empty (default) target or the specified target.
-
-Gnu Make
---------
-
-.. _xnt.bulid.make.make:
-.. function:: make(path="", target="")
-
- Invoke Gnu Make (*make*) in either the current working directory or the
- specified directory using the empty (default) target or the specified
- target.
-
-(.NET)Ant
----------
-
-.. _xnt.build.nant.nant:
-.. function:: nant(path="", target="")
-
- Invoke NAnt in either the current working directory or the specified
- directory using the empty (default) target or the specified target.
-
SCM Tasks
=========
diff --git a/xnt/build/ant.py b/xnt/build/ant.py
deleted file mode 100644
index 46de16b..0000000
--- a/xnt/build/ant.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env python
-
-# Xnt -- A Wrapper Build Tool
-# Copyright (C) 2012 Kenny Ballou
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import os
-import subprocess
-
-def ant(path="", target=""):
- cmd = ["ant", target]
- if path and os.path.exists(path):
- oldPath = os.path.abspath(os.getcwd())
- os.chdir(os.path.abspath(path))
- result = subprocess.call(cmd)
- if oldPath:
- os.chdir(oldPath)
- return result
diff --git a/xnt/build/cc.py b/xnt/build/cc.py
new file mode 100644
index 0000000..e4592ca
--- /dev/null
+++ b/xnt/build/cc.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+
+# Xnt -- A Wrapper Build Tool
+# Copyright (C) 2012 Kenny Ballou
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Common Compilers
+"""
+
+import os
+import logging
+import sys
+from xnt.tasks import call
+
+logger = logging.getLogger(__name__)
+
+def gcc(src, flags=[]):
+ """gcc compiler, non-named output file"""
+ return _gcc(src, flags)
+
+def gpp(src, flags=[]):
+ """g++ compiler, non-named output file"""
+ return _gcc(src, flags, "g++")
+
+def gcc_o(src, o, flags=[]):
+ """gcc compiler, with output file"""
+ return _gcc_o(src, o, flags)
+
+def gpp_o(src, o, flags=[]):
+ """g++ compiler, with output file"""
+ return _gcc_o(src, o, flags, "g++")
+
+def javac(src, flags=[]):
+ """Javac: compile Java programs"""
+ logger.info("Compiling %s", src)
+ cmd = __generateCommand(src, flags, "javac")
+ return __compile(cmd)
+
+def _gcc(src, flags=[], compiler="gcc"):
+ logger.info("Compiling %s", src)
+ return __compile(__generateCommand(src, flags, compiler))
+
+def _gcc_o(src, o, flags=[], compiler="gcc"):
+ logger.info("Compiling %s to %s", src, o)
+ cmd = __generateCommand(src, flags, compiler)
+ cmd.append("-o")
+ cmd.append(o)
+ return __compile(cmd)
+
+def __generateCommand(src, flags=[], compiler="gcc"):
+ cmd = [compiler, src]
+ for f in flags:
+ cmd.append(f)
+ return cmd
+
+def __compile(cmd):
+ return call(cmd)
+
+def __is_newer(a, b):
+ return os.path.getmtime(a) > os.path.getmtime(b)
diff --git a/xnt/build/make.py b/xnt/build/make.py
index 1fa0f3f..a9339a4 100644
--- a/xnt/build/make.py
+++ b/xnt/build/make.py
@@ -18,13 +18,26 @@
import os
import subprocess
+import logging
+
+
+def ant(path="", target=""):
+ cmd = ["ant", target]
+ return __run_in(path, lambda: subprocess.call(cmd))
def make(path="", target=""):
cmd = ["make", target]
+ return __run_in(path, lambda: subprocess.call(cmd))
+
+def nant(path="", target=""):
+ cmd = ["nant", target]
+ return __run_in(path, lambda: subprocess.call(cmd))
+
+def __run_in(path, f):
+ oldPath = os.path.abspath(os.getcwd())
if path and os.path.exists(path):
- oldPath = os.path.abspath(os.getcwd())
os.chdir(os.path.abspath(path))
- result = subprocess.call(cmd)
+ result = f()
if oldPath:
os.chdir(oldPath)
return result
diff --git a/xnt/build/nant.py b/xnt/build/nant.py
deleted file mode 100644
index 0d35c90..0000000
--- a/xnt/build/nant.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env python
-
-# Xnt -- A Wrapper Build Tool
-# Copyright (C) 2012 Kenny Ballou
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import os
-import subprocess
-
-def nant(path="", target=""):
- cmd = ["nant", target]
- if path and os.path.exists(path):
- oldPath = os.path.abspath(os.getcwd())
- os.chdir(os.path.abspath(path))
- result = subprocess.call(cmd)
- if oldPath:
- os.chdir(oldPath)
- return result
diff --git a/xnt/tests/compilercollectiontests.py b/xnt/tests/compilercollectiontests.py
new file mode 100644
index 0000000..ba470b7
--- /dev/null
+++ b/xnt/tests/compilercollectiontests.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+
+# Xnt -- A Wrapper Build Tool
+# Copyright (C) 2012 Kenny Ballou
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import sys
+import os
+import shutil
+import xnt.build.cc as cc
+import unittest
+
+#http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python
+def which(program):
+ def is_exe(fpath):
+ return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+
+ fpath, fname = os.path.split(program)
+ if fpath:
+ if is_exe(program):
+ return program
+ else:
+ for path in os.environ["PATH"].split(os.pathsep):
+ path = path.strip('"')
+ exe_file = os.path.join(path, program)
+ if is_exe(exe_file):
+ return exe_file
+
+ return None
+
+@unittest.skipUnless(which("gcc"), "gcc is not in your path")
+class gccTests(unittest.TestCase):
+ def setUp(self):
+ os.mkdir("temp")
+ with open("temp/hello.c", "w") as f:
+ f.write("""
+ #include <stdio.h>
+ int main() {
+ printf("Hello, World!\\n");
+ return 0;
+ }
+ """)
+
+ def tearDown(self):
+ shutil.rmtree("temp")
+
+ def test_gcc(self):
+ oldPath = os.getcwd()
+ os.chdir("temp")
+ cc.gcc("hello.c")
+ self.assertTrue(os.path.isfile("a.out"))
+ os.chdir(oldPath)
+
+ def test_gcc_o(self):
+ cc.gcc_o("temp/hello.c", "temp/hello")
+ self.assertTrue(os.path.isfile("temp/hello"))
+
+@unittest.skipUnless(which("g++"), "g++ is not in your path")
+class gppTests(unittest.TestCase):
+ def setUp(self):
+ os.mkdir("temp")
+ with open("temp/hello.cpp", "w") as f:
+ f.write("""
+ #include <iostream>
+ int main() {
+ std::cout << "Hello, World!" << std::endl;
+ return 0;
+ }
+ """)
+
+ def tearDown(self):
+ shutil.rmtree("temp")
+
+ def test_gpp(self):
+ oldPath = os.getcwd()
+ os.chdir("temp")
+ cc.gpp("hello.cpp")
+ self.assertTrue("a.out")
+ os.chdir(oldPath)
+
+ def test_gpp_o(self):
+ cc.gpp_o("temp/hello.cpp", "temp/hello")
+ self.assertTrue(os.path.isfile("temp/hello"))
+
+@unittest.skipUnless(which("javac"), "javac is not in your path")
+class javacTests(unittest.TestCase):
+ def setUp(self):
+ os.mkdir("temp")
+ with open("temp/hello.java", "w") as f:
+ f.write("""
+ class hello {
+ public static void main(String[] args) {
+ System.out.println("Hello, World!");
+ }
+ }
+ """)
+
+ def tearDown(self):
+ shutil.rmtree("temp")
+
+ def test_javac(self):
+ oldPath = os.getcwd()
+ os.chdir("temp")
+ cc.javac("hello.java")
+ self.assertTrue(os.path.isfile("hello.class"))
+ os.chdir(oldPath)
+
+if __name__ == "__main__":
+ unittest.main()