A small build automation tool that ships with your software.
Copyright © 2017 Raise Authors
Last updated on May 12th 2017
https://github.com/workhorsy/raise
Raise is licensed as freely as possible, in the hopes that it will be compatible with most other software licenses.
The Raise software is licensed under The MIT License .
The Raise documentation is license under The Creative Commons Attribution License v3.0 .
Copyright © 2012 - 2017 Matthew Brennan Jones <matthew.brennan.jones@gmail.com>
Other authors please add your copyright and contact info here.
If you find any errors, bugs, or misinformation, please report a bug at https://github.com/workhorsy/raise or contact one of the authors.
Documentation is provided in the docs/index.html file. It is generated from the Python Mako Template file docs/templates/index.html.mako.
Warning! Because Raise uses scripts to generate the documentation, you won't be able to generate the documentation unless you have all the compilers and tools installed. Doing this also requires root, because it runs all the code examples to get the actual output from those code examples.
To generate the index.html file you can run:
python generate_documentation.py
Any changes should be added to the index.html.mako file, as it will wipe out any changes in index.html when generate_documentation.py is run.
The philosophy of Raise is that it says what it is doing. Not how it is doing it. It only shows the details when something goes wrong. That way the build output does not fill with information you don't need. It shows the output for each step of the build process, as its own line.
Raise should not be installed into your Operating System. It is designed to run from inside your project's directory.
Raise consists of a small shim script called "raise" and a directory of modules called ".lib_raise". The "raise" shim is safe to save into your VCS along with your source code. It is small (10kB) and should not change very often. All the ".lib_raise" modules are automatically downloaded by the "raise" shim. You should not check the ".lib_raise" directory into your VCS.
If you want to check the raise modules into your VCS (So your project will build without needing an Internet connection). You should rename the ".lib_raise" directory to "lib_raise". This is also a good idea to do before you release your source code as a compressed file.
The file hierarchy of Raise looks like this:
# Your script that builds your software rscript # The shim that gets everything ready raise # The modules that are automatically downloaded .lib_raise-+ |-cpuinfo.py |-findlib.py |-findlib_server.py |-lib_raise.py |-lib_raise_ar.py |-lib_raise_c.py |-lib_raise_config.py |-lib_raise_cpu.py |-lib_raise_csharp.py |-lib_raise_cxx.py |-lib_raise_d.py |-lib_raise_find.py |-lib_raise_fs.py |-lib_raise_helpers.py |-lib_raise_java.py |-lib_raise_linker.py |-lib_raise_process.py |-lib_raise_python.py |-lib_raise_terminal.py |-lib_raise_users.py `-osinfo.pyThere are eight basic OS types:
Fully supported.
Has been tested on FreeBSD, and PCBSD, but not on OpenBSD, NetBSD, or DragonflyBSD.
wget https://raw.githubusercontent.com/workhorsy/raise/master/raise
chmod +x raise
./raise
Bugs:
Fully Supported.
wget https://raw.githubusercontent.com/workhorsy/raise/master/raise
chmod +x raise
./raise
Partially supported.
Can build basic exes, shared/static libraries, but not install anything, or search for programs/libraries. Not yet tested on BeOS.
wget https://raw.githubusercontent.com/workhorsy/raise/master/raise
chmod +x raise
./raise
Fully supported.
Primarily developed on Linux with kernel 2.6 and greater. Tested primarily on Ubuntu, Debian, Linux Mint, Fedora, and Centos. It should "just work" on other Linux distros.
wget https://raw.githubusercontent.com/workhorsy/raise/master/raise
chmod +x raise
./raise
Not supported.
None of the mobile OSes are supported. They either do not support the required compilers, or are locked down too tightly to use. Hopefully this will change in the future.
Partially Supported
Can build basic exes, shared/static libraries, and find programs/libraries.
Bugs:
wget https://raw.githubusercontent.com/workhorsy/raise/master/raise
chmod +x raise
./raise
Fully supported.
Tested on Open Indiana, Open Solaris, and Open SXCE. Not yet tested on Oracle Solaris.
wget https://raw.githubusercontent.com/workhorsy/raise/master/raise
chmod +x raise
./raise
Partially supported.
Tested on Windows XP, Windows 7, and Windows 8. There are still issues with building and finding C/C++ libraries on Windows. It is recommended that Windows users use Cygwin.
Download from https://github.com/workhorsy/raise
python raise
Bugs:
Has not been tested on Windows Vista or Windows RT.
Source code can be checked out using the Git VCS.
git clone
cd raise/examples/c_simple
./raise test
C and C++ are fully supported with GCC, and Clang. MS cl.exe support is not yet complete.
D is fully supported with DMD, and LDC. GDC support is disabled, because the packages in debian/ubuntu are broken.
C# works with Mono and MS .NET. Some advanced features such as installing into the GAC have not been implemented.
Java works with OpenJDK 7.
Raise uses a specific format to show messages to the user. It prints what it is going to do. Then when it is done, it prints an emoticon for success, warning, or failure. By using this format, it should be easy for anyone to quickly tell if everything is okay or not.
For example this prints out "Building C++ program 'main.exe' ..." when it starts. Then prints a ":)" when it is successful.
Building C++ program 'main.exe' ... :)
:) - A green smile represents success. This is used when a command has a return code of zero, and has nothing printed to stderr.
:\ - A yellow half smile represents success with a warning. This is used when a command has a return code of zero, but has something printed to stderr.
:( - A red frown represents failure. This is used when a command has a return code that is not zero.
One of the huge issue in dealing with different platforms, is how they handle file extensions. Many have different extensions for the same type of file. For example Windows typically uses .exe for executable, and .obj for object. While Linux typically uses no extension for executable, and .o for object.
Raise gets around this by having its own list of file extensions and mapping them to the native type for that Operating System.
For example when building a C program you would say:
C.build_program('main.exe', ['main.c'])
On Windows it will create "main.exe", but on Linux it will create "main".
To see the mappings, look at the section for each language.
# Most of this section requires the modules:
import lib_raise_process as Process
The fundamental way that Raise works, is that it wraps function calls. It says that it is going to call a function, calls the function, then prints an emoticon for success or failure.
For example: Below the Process.do_on_fail_exit function will print "Running simple_function", call the function, then print a smiley on success. The function output will be printed below the smiley.
def simple_function():
print('blah')
Process.do_on_fail_exit(
"Running simple_function", "It failed", simple_function)
Running that code will produce this result:
Running simple_function ... :)
blah
If the function Process.do_on_fail_exit is called on a function that raises an error. The function will print "Running simple_function", call the function while catching the exception, print the frown, then print the failure message "It failed". The function output will be printed below the failure message.
def simple_function():
raise Exception('broken')
Process.do_on_fail_exit(
"Running simple_function", "It failed", simple_function)
Running that code will produce this result:
Running simple_function ........................................................:(
It failed Exiting ...
broken
If you do not want the script to exit when the function is_broken throws an exception, you can use the Process.do_on_fail_pass function. It will ignore any exceptions raised by the functions.
def is_broken():
raise Exception('broken')
def is_not_broken():
pass
Process.do_on_fail_pass("Running is_not_broken", is_not_broken)
Process.do_on_fail_pass("Running is_broken", is_broken)
Running that code will produce this result:
Running is_not_broken ... :) Running is_broken ... :)
If you want to run a command and have its result printed, you can use the Process.run_print convenience function. The command itself will be printed, then the result of the command.
Process.run_print("uptime")
Produces the result:
Running command ... :)
uptime
17:15:09 up 3:43, 4 users, load average: 0.12, 0.13, 0.14
If you want to run a command and get its standard output, you can use the Process.run_and_get_stdout convenience function.
result = Process.run_and_get_stdout("uptime")
print(result)
Produces the result:
17:15:09 up 3:43, 4 users, load average: 0.12, 0.13, 0.14
# Most of this section requires the modules:
import lib_raise_users as Users
If you want to ensure that a script is run as root. You can use the Users.require_root function. If the script is not run as root, it will print an error and exit.
Example:
def users_running_as_root():
# Print the user id
print('Effective user id: {0}'.format(os.getuid()))
# Will print an error and exit if the user is NOT root
Users.require_root()
Example output when run as root:
Effective user id: 0
Example output when NOT run as root:
Effective user id: 1000
Must be run as root. Exiting ...
If you want to ensure that a script is run as a normal user, you can use the Users.require_not_root function. If the script is run as root, it will print an error and exit.
Example:
def users_running_as_a_normal_user():
# Print the user id
print('Effective user id: {0}'.format(os.getuid()))
# Will print an error and exit if the user is root
Users.require_not_root()
Example output when run as root:
Effective user id: 0
Must not be run as root. Exiting ...
Example output when NOT run as root:
Effective user id: 1000
Often you will need do some actions as root, and others as a normal user, all in the same script. A common example is to compile a program as a normal user, then install it as root. You can do this by running the script as root, then using the function Users.do_as_normal_user to temporarily step down as a normal user.
Example:
def users_privilege_escalation():
# User id by default
print('Effective user id: {0}'.format(os.geteuid()))
# User id when running as a normal user
def cb():
print('Effective user id: {0}'.format(os.geteuid()))
Users.do_as_normal_user(cb)
# User id by default
print('Effective user id: {0}'.format(os.geteuid()))
Example output:
Effective user id: 0 Effective user id: 1000 Effective user id: 0
When running a script with a privilege escalation tool such as sudo, you often need to get the actual user name. Most python functions such as getpass.getuser will return 'root', because it is actually being run as root. To get the actual user name, you can use the Users.get_normal_user_name function.
Example:
def users_user_name():
import getpass
print('Current user name: {0}'.format(getpass.getuser()))
print('Normal user name: {0}'.format(Users.get_normal_user_name()))
Example output when NOT run as root:
Current user name: matt Normal user name: matt
Example output when run as root:
Current user name: root Normal user name: matt
When running a script with a privilege escalation tool such as sudo, you often need to get the actual user id. Most python functions such as os.getuid and os.geteuid will return 0, because it is actually being run as root.
Example:
def users_user_id():
print('Current user id: {0}'.format(os.getuid()))
print('Normal user id: {0}'.format(Users.get_normal_user_id()))
Example output when NOT run as root:
Current user id: 1000 Normal user id: 1000
Example output when run as root:
Current user id: 0 Normal user id: 1000
# Most of this section requires the modules:
import lib_raise_fs as FS
change_dir(name)
Uses the standard Python os.chdir
function to change to the name directory.
Example:
def fs_change_dir():
FS.change_dir('example')
Example output:
Changing to dir 'example' ... :)
move_file(source, dest)
Uses the standard Python shutil.move function to move the file
source to dest.
Example:
def fs_move_file():
FS.move_file('one', 'two')
Example output:
Moving the file 'one' to 'two' ... :)
copy_file(source, dest)
Uses the standard Python shutil.copy2 function to copy the file
source to dest.
Example:
def fs_copy_file():
FS.copy_file('one', 'two')
Example output:
Copying the file 'one' to 'two' ... :)
copy_new_file(source, dest)
Copies the file only if dest does not exist, or source is
different from dest.
Example:
def fs_copy_new_file():
FS.copy_new_file('one', 'two')
Example output:
Copying the file 'one' to 'two' ... :)
copy_dir(source, dest, symlinks = False)
Uses the standard Python shutil.copytree function to recursively copy
the directory from source to dest. If
symlinks is True, symlinks remail links. If symlinks is False the links
are replaced with copies of the actual data.
Example:
def fs_copy_dir():
FS.copy_dir('example', 'new_example', symlinks = False)
Example output:
Copying the dir 'example' to 'new_example' ... :)
make_dir(source, ignore_failure = False)
Uses the standard Python os.mkdir function to make the
directory source. If ignore_failure
is False, any errors will be ignored.
Example:
def fs_make_dir():
FS.make_dir('example', ignore_failure = True)
Example output:
Making the dir 'example' ... :)
remove_dir(name, and_children = False)
Uses the standard Python shutil.rmtree function to remove the
directory name. If name is the current
directory, it will display an error. If and_children
is True it will remove any child directories.
Example:
def fs_remove_dir():
FS.remove_dir('example', and_children = True)
Example output:
Removing the dir 'example' ... :)
remove_file(name, ignore_failure = False)
Uses the standard Python os.rmdir function to remove the
file name. If ignore_failure
is True it will ignore any errors.
Example:
def fs_remove_file():
FS.remove_file('does_not_exist', ignore_failure = True)
Example output:
Removing the file 'does_not_exist' ... :)
remove_binaries(name)
Will remove any files that start with name, and have the
extensions .exe, .o, .obj, .so, .a, .dll, .lib, .pyc, .exe.mdb, .dll.mdb,
.jar, .class.
Example:
def fs_remove_binaries():
FS.remove_binaries('main')
Example output:
Removing binaries 'main' ... :)
symlink(source, link_name)
Uses the standard Python os.symlink function to create a
symlink from source to link_name.
Example:
def fs_symlink():
FS.symlink('example', 'example_link')
Example output:
Symlinking 'example' to 'example_link' ... :)
# Most of this section requires the modules:
import lib_raise_terminal as Terminal
If you want to print your own OK message, you can use the Terminal.status and Terminal.ok functions.
Example:
def terminal_ok():
Terminal.status("Looks like things will be okay")
Terminal.ok()
Example output:
Looks like things will be okay ... :)
If you want to print your own warning message, you can use the Terminal.status and Terminal.warning functions.
Example:
def terminal_warning():
Terminal.status("Looks like this may give a warning")
Terminal.warning("Yep. Here is the warning")
Example output:
Looks like this may give a warning .........................................:\
Yep. Here is the warning
If you want to print your own fail message, you can use the Terminal.status and Terminal.fail functions.
Example:
def terminal_fail():
Terminal.status("This may fail")
Terminal.fail("Yep. Here is the fail message")
Example output:
This may fail ..............................................................:(
Yep. Here is the fail message
# Most of this section requires the modules:
import lib_raise_find as Find
import lib_raise_python as Python
Raise has built in functionality for finding programs, libraries, and header files. It tries to use the OSes native way of searching for files. If that is not available, or does not find anything, it will fall-back to searching the file system. Raise can also include the version number when searching for libraries and header files.
Raise searches the OS packaging sources in this order:Version numbers use the standard format major.minor.micro. They are stored in a named tuple. You can access the complete version as a tuple. And you can access the major, minor, or micro section as a property.
ver # (1, 2, 0)
ver.major # 1
ver.minor # 2
ver.micro # 0
When creating your version requirements, you have to use a string:
# Version 1.2.0
'ver == (1, 2, 0)'
# Version 1.2.0 the long way
'ver.major==1 and ver.minor==2 and ver.micro==0'
# Version 1.9 or greater
'ver >= (1, 9)'
# Version 1
'ver.major == 1'
# Version 1.X with an odd minor number like 1.3 not 1.2
'ver >= (1.0) and ver.minor % 2'
You can find a program, by searching for it with the Find.program_paths function. You can also use regular expressions in the name. There is currently no standard way to specify what version of the program you want to find.
Example:
def find_finding_programs():
paths = Find.program_paths('gcc')
print(paths)
paths = Find.program_paths('g++', r'g++-[0-9|\.]*')
print(paths)
Example output:
['/usr/bin/gcc'] ['/usr/bin/g++', '/usr/bin/g++-5']
You can make sure a program is installed, by using the Find.require_programs function. If the program is not installed, it will print an error and exit. There is currently no way to specify what version of the program you want to require.
Example:
def find_requiring_programs():
Find.require_programs(['gcc'])
Example output:
Checking for program 'gcc' ... :)
You can find a library, by searching for it with the Find.get_static_library and Find.get_shared_library functions. Optionally you can use the version lambda to specify what version you want.
Example:
def find_finding_libraries():
# SDL Library any version
print(Find.get_static_library('libSDL'))
print(Find.get_shared_library('libSDL'))
# SDL Library at least version 1.2
print(Find.get_shared_library('libSDL', 'ver >= (1, 2)'))
# SDL Library of version 1.X
print(Find.get_shared_library('libSDL', 'ver.major == 1'))
Example output:
/usr/lib/x86_64-linux-gnu/libSDL.a /usr/lib/x86_64-linux-gnu/libSDL.so /usr/lib/x86_64-linux-gnu/libSDL.so /usr/lib/x86_64-linux-gnu/libSDL.so
You can make sure a library is installed, by using the Find.require_static_library and Find.require_shared_library functions. If the library is not installed, it will print an error and exit. Optionally you can use the version lambda to specify what version you want.
Example:
def find_requiring_libraries():
# SDL Library any version
Find.require_static_library('libSDL')
Find.require_shared_library('libSDL')
# SDL Library at least version 1.2
Find.require_shared_library('libSDL', 'ver >= (1, 2)')
# SDL Library of version 1.X
Find.require_shared_library('libSDL', 'ver.major == 1')
Example output:
Checking for static library 'libSDL' ... :) Checking for shared library 'libSDL' ... :) Checking for shared library 'libSDL' ... :) Checking for shared library 'libSDL' ... :)
You can find a header file, by searching for it with the Find.get_header_file function. Optionally you can use the version lambda to specify what version you want.
Example:
def find_finding_headers():
# SDL Library any version
print(Find.get_header_file('libSDL'))
# SDL Library at least version 1.2
print(Find.get_header_file('libSDL', 'ver >= (1, 2)'))
# SDL Library of version 1.X
print(Find.get_header_file('libSDL', 'ver.major == 1'))
Example output:
/usr/include/SDL/SDL.h /usr/include/SDL/SDL.h /usr/include/SDL/SDL.h
You can make sure a header file is installed, by using the Find.require_header_file function. If the header is not installed, it will print an error and exit. Optionally you can use the version lambda to specify what version you want.
Example:
def find_requiring_headers():
# SDL Library any version
Find.require_header_file('libSDL')
# SDL Library at least version 1.2
Find.require_header_file('libSDL', 'ver >= (1, 2)')
# SDL Library of version 1.X
Find.require_header_file('libSDL', 'ver.major == 1')
Example output:
Checking for header file 'libSDL' ... :) Checking for header file 'libSDL' ... :) Checking for header file 'libSDL' ... :)
You can search for environmental variables by using the Find.require_environmental_variable function.
Example:
def find_requiring_environmental_variable():
# Require that PATH exists
Find.require_environmental_variable('PATH')
Example output:
Checking for environmental variable 'PATH' ... :)
You can make sure Python modules are installed by using the Python.require_python_modules function.
Example:
def find_requiring_python_modules():
# Require that os, sys, and platform are installed
Python.require_python_modules(['os', 'sys', 'platform'])
Example output:
Checking for python module 'os' ... :) Checking for python module 'sys' ... :) Checking for python module 'platform' ... :)
# Most of this section requires the modules:
import lib_raise_c as C
import lib_raise_ar as AR
Many C compilers/OSes use different extensions for different types of files. To get around this limitation, you can use the file extension for the Raise rows below, and it will automatically be mapped to the OS type below.
Raise | Cygwin | Windows | OS X | Linux/Unix | |
---|---|---|---|---|---|
Executable | .exe | .exe | .exe | ||
Object | .o | .o | .obj | .o | .o |
Shared Library | .so | .so | .dll | .dylib | .so |
Static Library | .a | .a | .lib | .a | .a |
Raise supports the GCC, Clang, and MS cl.exe C compilers. The compiler is abstracted away in a generalized way, as to make it so you don't have to worry about compiler specific functionality.
You can select the best C compiler for your platform by using the C.get_default_compiler function.
You can also select the compiler specifically by using the C.c_compilers dictionary. Be careful as only compilers that were found by Raise will be in the dictionary.
Example:
def c_compilers():
cc = C.get_default_compiler()
# Print the compiler name and path for fun
print("name: {0}".format(cc._name))
print("path: {0} ".format(cc._path))
cc = C.c_compilers['clang']
# Print the compiler name and path for fun
print("name: {0}".format(cc._name))
print("path: {0} ".format(cc._path))
Example output:
name: gcc path: /usr/bin/gcc name: clang path: /usr/bin/clang
After the compiler is selected, it can be configured using the properties.
Example:
def c_compiler_setup():
# Get a C compiler
cc = C.get_default_compiler()
# Compiler setup
cc.debug = True
cc.standard = C.Standard.std2011
cc.position_independent_code = True
cc.optimize_level = 2
cc.warnings_all = True
cc.warnings_extra = True
cc.warnings_as_errors = True
cc.compile_time_flags = ['SDL=true']
# Print environmental variables to see what happens under the hood
print("$CC: {0}".format(cc.cc))
print("$CFLAGS: {0}".format(cc.cflags))
Example output:
$CC: gcc $CFLAGS: -g -std=c11 -fPIC -Wall -Wextra -Werror -O2 -DSDL=true
C object files can be built using the C.build_object function.
Example:
def c_building_object():
# Get and setup the C compiler
cc = C.get_default_compiler()
cc.debug = True
# Build the object
cc.build_object('main.o', ['main.c'])
Example output:
Building C object 'main.o' ... :)
C programs can be built using the C.build_program function.
Example:
def c_building_program():
# Get and setup the C compiler
cc = C.get_default_compiler()
cc.debug = True
# Build the program
cc.build_program('main.exe', ['main.c'])
Example output:
Building C program 'main.exe' ... :)
C shared library can be built using the C.build_shared_library function. C static libraries can be built using the AR.build_static_library function.
Example:
def c_building_library():
# Get and setup the C compiler
cc = C.get_default_compiler()
cc.debug = True
# Build the library into an object
cc.build_object('libexample.o', ['libexample.c'])
# Build the library as a shared and static library
cc.build_shared_library('libexample.so', ['libexample.o'])
AR.build_static_library('libexample.a', ['libexample.o'])
Example output:
Building C object 'libexample.o' ... :) Building C shared library 'libexample.so' ... :) Building static library 'libexample.a' ... :)
C programs can be installed with the C.install_program function, and uninstalled with the C.uninstall_program function.
Example:
def c_program_installation_and_uninstallation():
# Get and setup the C compiler
cc = C.get_default_compiler()
cc.debug = True
# Build the program
cc.build_program('main.exe', ['main.c'])
# Install the program
C.install_program('main.exe')
FS.remove_binaries('main')
# Run the C program from the system
C.run_print('main.exe')
# Uninstall the program
C.uninstall_program('main.exe')
Example output:
Building C program 'main.exe' ... :) Installing the program 'main.exe' ... :) Removing binaries 'main' ... :) Running C program ... :) main.exe Hello World! Uninstalling the program 'main.exe' ... :)
C libraries can be installed with the C.install_library function, and uninstalled with the C.uninstall_library function.
Example:
def c_library_installation_and_uninstallation():
# Get and setup the C compiler
cc = C.get_default_compiler()
cc.debug = True
# Build the library
cc.build_object('libexample.o', ['libexample.c'])
cc.build_shared_library('libexample.so', ['libexample.o'])
# Install the library
C.install_library('libexample.so')
# Uninstall the library
C.uninstall_library('libexample.so')
Example output:
Building C object 'libexample.o' ... :) Building C shared library 'libexample.so' ... :) Installing the library 'libexample.so' ... :) Uninstalling the library 'libexample.so' ... :)
C headers can be installed with the C.install_header function, and uninstalled with the C.uninstall_header function.
Example:
def c_header_installation_and_uninstallation():
# Get and setup the C compiler
cc = C.get_default_compiler()
cc.debug = True
# Install the header
C.install_header('libexample.h')
# Uninstall the header
C.uninstall_header('libexample.h')
Example output:
Installing the header 'libexample.h' ... :) Uninstalling the header 'libexample.h' ... :)
C programs can be ran with the C.run_print function.
Example:
def c_running_and_printing():
# Get and setup the C compiler
cc = C.get_default_compiler()
cc.debug = True
# Build the program
cc.build_program('main.exe', ['main.c'])
# Run the C program
C.run_print('./main.exe')
Example output:
Building C program 'main.exe' ... :) Running C program ... :) ./main.exe Hello World!
# Most of this section requires the modules:
import lib_raise_cxx as CXX
import lib_raise_ar as AR
Many C++ compilers/OSes use different extensions for different types of files. To get around this limitation, you can use the file extension for the Raise rows below, and it will automatically be mapped to the OS type below.
Raise | Cygwin | Windows | OS X | Linux/Unix | |
---|---|---|---|---|---|
Executable | .exe | .exe | .exe | ||
Object | .o | .o | .obj | .o | .o |
Shared Library | .so | .so | .dll | .so | .dylib |
Static Library | .a | .a | .lib | .a | .a |
Raise supports the GCC, Clang, and MS cl.exe C++ compilers. The compiler is abstracted away in a generalized way, as to make it so you don't have to worry about compiler specific functionality.
You can select the best C++ compiler for your platform by using the CXX.get_default_compiler function.
You can also select the compiler specifically by using the CXX.cxx_compilers dictionary. Be careful as only compilers that were found by Raise will be in the dictionary.
Example:
def cxx_compilers():
cxx = CXX.get_default_compiler()
# Print the compiler name and path for fun
print("name: {0}".format(cxx._name))
print("path: {0} ".format(cxx._path))
cxx = CXX.cxx_compilers['clang++']
# Print the compiler name and path for fun
print("name: {0}".format(cxx._name))
print("path: {0} ".format(cxx._path))
Example output:
name: g++ path: /usr/bin/g++ name: clang++ path: /usr/bin/clang++
After the compiler is selected, it can be configured using the properties.
Example:
def cxx_compiler_setup():
# Get a C++ compiler
cxx = CXX.get_default_compiler()
# Compiler setup
cxx.debug = True
cxx.standard = CXX.Standard.std2011
cxx.position_independent_code = True
cxx.optimize_level = 2
cxx.warnings_all = True
cxx.warnings_extra = True
cxx.warnings_as_errors = True
cxx.compile_time_flags = ['SDL=true']
# Print environmental variables to see what happens under the hood
print("$CXX: {0}".format(cxx.cxx))
print("$CXXFLAGS: {0}".format(cxx.cxxflags))
Example output:
$CXX: g++ $CXXFLAGS: -g -std=c++11 -fPIC -Wall -Wextra -Werror -O2 -DSDL=true
C++ object files can be built using the CXX.build_object function.
Example:
def cxx_building_object():
# Get and setup the C++ compiler
cxx = CXX.get_default_compiler()
cxx.debug = True
# Build the object
cxx.build_object('main.o', ['main.cc'])
Example output:
Building C++ object 'main.o' ... :)
C++ programs can be built using the CXX.build_program function.
Example:
def cxx_building_program():
# Get and setup the C++ compiler
cxx = CXX.get_default_compiler()
cxx.debug = True
# Build the program
cxx.build_program('main.exe', ['main.cc'])
Example output:
Building C++ program 'main.exe' ... :)
C++ shared library can be built using the CXX.build_shared_library function. C++ static libraries can be built using the AR.build_static_library function.
Example:
def cxx_building_library():
# Get and setup the C++ compiler
cxx = CXX.get_default_compiler()
cxx.debug = True
# Build the library into an object
cxx.build_object('libadd.o', ['libadd.cc'])
# Build the library as a shared and static library
cxx.build_shared_library('libadd.so', ['libadd.o'])
AR.build_static_library('libadd.a', ['libadd.o'])
Example output:
Building C++ object 'libadd.o' ... :) Building C++ shared library 'libadd.so' ... :) Building static library 'libadd.a' ... :)
C++ programs can be installed with the CXX.install_program function, and uninstalled with the CXX.uninstall_program function.
Example:
def cxx_program_installation_and_uninstallation():
# Get and setup the C++ compiler
cxx = CXX.get_default_compiler()
cxx.debug = True
# Build the program
cxx.build_program('main.exe', ['main.cc'])
# Install the program
CXX.install_program('main.exe')
FS.remove_binaries('main')
# Run the C++ program from the system
CXX.run_print('main.exe')
# Uninstall the program
CXX.uninstall_program('main.exe')
Example output:
Building C++ program 'main.exe' ... :) Installing the program 'main.exe' ... :) Removing binaries 'main' ... :) Running C++ program ... :) main.exe Hello World! Uninstalling the program 'main.exe' ... :)
C++ libraries can be installed with the CXX.install_library function, and uninstalled with the CXX.uninstall_library function.
Example:
def cxx_library_installation_and_uninstallation():
# Get and setup the C++ compiler
cxx = CXX.get_default_compiler()
cxx.debug = True
# Build the library
cxx.build_object('libadd.o', ['libadd.cc'])
cxx.build_shared_library('libadd.so', ['libadd.o'])
# Install the library
CXX.install_library('libadd.so')
# Uninstall the library
CXX.uninstall_library('libadd.so')
Example output:
Building C++ object 'libadd.o' ... :) Building C++ shared library 'libadd.so' ... :) Installing the library 'libadd.so' ... :) Uninstalling the library 'libadd.so' ... :)
C++ headers can be installed with the CXX.install_header function, and uninstalled with the CXX.uninstall_header function.
Example:
def cxx_header_installation_and_uninstallation():
# Get and setup the C++ compiler
cxx = CXX.get_default_compiler()
cxx.debug = True
# Install the header
CXX.install_header('libadd.h')
# Uninstall the header
CXX.uninstall_header('libadd.h')
Example output:
Installing the header 'libadd.h' ... :) Uninstalling the header 'libadd.h' ... :)
C++ programs can be ran with the CXX.run_print function.
Example:
def cxx_running_and_printing():
# Get and setup the C++ compiler
cxx = CXX.get_default_compiler()
cxx.debug = True
# Build the program
cxx.build_program('main.exe', ['main.cc'])
# Run the C++ program
CXX.run_print('./main.exe')
Example output:
Building C++ program 'main.exe' ... :) Running C++ program ... :) ./main.exe Hello World!
# Most of this section requires the modules:
import lib_raise_d as D
Many D compilers/OSes use different extensions for different types of files. To get around this limitation, you can use the file extension for the Raise rows below, and it will automatically be mapped to the OS type below.
Raise | Cygwin | Windows | Standard | |
---|---|---|---|---|
Executable | .exe | .exe | .exe | |
Object | .o | .obj | .obj | .o |
Shared Library | .so | .dll | .dll | .so |
Static Library | .a | .lib | .lib | .a |
Raise supports the DMD, and LDC, D compilers (not GDC). The compiler is abstracted away in a generalized way, as to make it so you don't have to worry about compiler specific functionality.
You can select the best D compiler for your platform by using the D.get_default_compiler function.
You can also select the compiler specifically by using the D.d_compilers dictionary. Be careful as only compilers that were found by Raise will be in the dictionary.
Example:
def d_compilers():
dc = D.get_default_compiler()
# Print the compiler name and path for fun
print("name: {0}".format(dc._name))
print("path: {0} ".format(dc._path))
dc = D.d_compilers['ldc']
# Print the compiler name and path for fun
print("name: {0}".format(dc._name))
print("path: {0} ".format(dc._path))
Example output:
name: dmd path: /usr/bin/dmd name: ldc path: /usr/bin/ldc2
After the compiler is selected, it can be configured using the properties.
Example:
def d_compiler_setup():
# Get a D compiler
dc = D.get_default_compiler()
# Compiler setup
dc.debug = True
dc.optimize = True
dc.warnings_all = True
dc.unittest = True
dc.compile_time_flags = ['SDL=true']
# Print environmental variables to see what happens under the hood
print("$DC: {0}".format(dc.dc))
print("$DFLAGS: {0}".format(dc.dflags))
Example output:
$DC: dmd $DFLAGS: -g -w -O -unittest -version=SDL=true
D object files can be built using the D.build_object function.
Example:
def d_building_object():
# Get and setup the D compiler
dc = D.get_default_compiler()
dc.debug = True
# Build the object
dc.build_object('main.o', ['main.d'])
Example output:
Building D object 'main.o' ... :)
D programs can be built using the D.build_program function.
Example:
def d_building_program():
# Get and setup the D compiler
dc = D.get_default_compiler()
dc.debug = True
# Build the program
dc.build_program('main.exe', ['main.d'])
Example output:
Building D program 'main.exe' ... :)
D static library can be built using the D.build_static_library function. The main DMD compiler and spec does not yet support building shared libraries.
Example:
def d_building_library():
# Get and setup the D compiler
dc = D.get_default_compiler()
dc.debug = True
# Build the library
dc.build_object('libsubtract.o', ['libsubtract.d'])
dc.build_static_library('libsubtract.a', ['libsubtract.o'])
Example output:
Building D object 'libsubtract.o' ... :) Building D static library 'libsubtract.a' ... :)
D interface can be built using the D.build_interface function.
Example:
def d_building_interface():
# Get and setup the D compiler
dc = D.get_default_compiler()
dc.debug = True
# Build the interface
dc.build_interface('libsubtract.d')
Example output:
Building D interface 'libsubtract.di' ... :)
D programs can be installed with the D.install_program function, and uninstalled with the D.uninstall_program function.
Example:
def d_program_installation_and_uninstallation():
# Get and setup the D compiler
dc = D.get_default_compiler()
dc.debug = True
# Build the program
dc.build_program('main.exe', ['main.d'])
# Install the program
D.install_program('main.exe')
FS.remove_binaries('main')
# Run the D program from the system
D.run_print('main.exe')
# Uninstall the program
D.uninstall_program('main.exe')
Example output:
Building D program 'main.exe' ... :) Installing the program 'main.exe' ... :) Removing binaries 'main' ... :) Running D program ... :) main.exe Hello World! Uninstalling the program 'main.exe' ... :)
D libraries can be installed with the D.install_library function, and uninstalled with the D.uninstall_library function.
Example:
def d_library_installation_and_uninstallation():
# Get and setup the D compiler
dc = D.get_default_compiler()
dc.debug = True
# Build the library
dc.build_object('libsubtract.o', ['libsubtract.d'])
dc.build_static_library('libsubtract.a', ['libsubtract.o'])
# Install the library
D.install_library('libsubtract.a')
# Uninstall the library
D.uninstall_library('libsubtract.a')
Example output:
Building D object 'libsubtract.o' ... :) Building D static library 'libsubtract.a' ... :) Installing the library 'libsubtract.a' ... :) Uninstalling the library 'libsubtract.a' ... :)
D interfaces can be installed with the D.install_interface function, and uninstalled with the D.uninstall_interface function.
Example:
def d_interface_installation_and_uninstallation():
# Get and setup the D compiler
dc = D.get_default_compiler()
dc.debug = True
# Build the interface
dc.build_interface('libsubtract.d')
# Install the interface
D.install_interface('libsubtract.di')
# Uninstall the interface
D.uninstall_interface('libsubtract.di')
Example output:
Building D interface 'libsubtract.di' ... :) Installing the interface 'libsubtract.di' ... :) Uninstalling the interface 'libsubtract.di' ... :)
D programs can be ran with the D.run_print function.
Example:
def d_running_and_printing():
# Get and setup the D compiler
dc = D.get_default_compiler()
dc.debug = True
# Build the program
dc.build_program('main.exe', ['main.d'])
# Run the D program
D.run_print('./main.exe')
Example output:
Building D program 'main.exe' ... :) Running D program ... :) ./main.exe Hello World!
# Most of this section requires the modules:
import lib_raise_csharp as CS
Raise supports the Mono, and MS.NET C# compilers. The compiler is abstracted away in a generalized way, as to make it so you don't have to worry about compiler specific functionality.
You can select the best C# compiler for your platform by using the CS.get_default_compiler function.
You can also select the compiler specifically by using the CS.cs_compilers dictionary. Be careful as only compilers that were found by Raise will be in the dictionary.
Example:
def csharp_compilers():
csc = CS.get_default_compiler()
# Print the compiler name and path for fun
print("name: {0}".format(csc._name))
print("path: {0} ".format(csc._path))
csc = CS.cs_compilers['dmcs']
# Print the compiler name and path for fun
print("name: {0}".format(csc._name))
print("path: {0} ".format(csc._path))
Example output:
name: dmcs path: /usr/bin/dmcs name: dmcs path: /usr/bin/dmcs
After the compiler is selected, it can be configured using the properties.
Example:
def csharp_compiler_setup():
# Get a C# compiler
csc = CS.get_default_compiler()
# Compiler setup
csc.debug = True
csc.optimize = True
csc.warnings_all = True
csc.warnings_as_errors = True
# Print environmental variables to see what happens under the hood
print("$CSC: {0}".format(csc.csc))
print("$CSFLAGS: {0}".format(csc.csflags))
Example output:
$CSC: dmcs $CSFLAGS: -debug -warn:4 -warnaserror -optimize
C# programs can be built using the CS.build_program function.
Example:
def csharp_building_program():
# Get and setup the C# compiler
csc = CS.get_default_compiler()
csc.debug = True
# Build the program
csc.build_program('main.exe', ['main.cs'])
Example output:
Building C# program 'main.exe' .............................................:\
warning CS8001: SDK path could not be resolved
C# static library can be built using the CS.build_shared_library function.
Example:
def csharp_building_library():
# Get and setup the C# compiler
csc = CS.get_default_compiler()
csc.debug = True
# Build the library
csc.build_shared_library('math_helper.dll', ['math_helper.cs'])
Example output:
Building C# shared library 'math_helper.dll' ...............................:\
warning CS8001: SDK path could not be resolved
C# programs can be installed with the CS.install_program function, and uninstalled with the CS.uninstall_program function.
Example:
def csharp_program_installation_and_uninstallation():
# Get and setup the C# compiler
csc = CS.get_default_compiler()
csc.debug = True
# Build the program
csc.build_program('main.exe', ['main.cs'])
# Install the program
CS.install_program('main.exe', 'csharp_example')
FS.remove_binaries('main')
# Run the C# program from the system
#FIXME: CS.run_print does not work on Linux, because when installed it runs
# the app from a shell script that does "mono blah.exe".
#CS.run_print('main.exe')
findlib.run_print("main")
# Uninstall the program
CS.uninstall_program('main.exe', 'csharp_example')
Example output:
Building C# program 'main.exe' .............................................:\ warning CS8001: SDK path could not be resolved Installing the program 'main.exe' ... :) Removing binaries 'main' ... :) Running command ... :) main Hello World! Uninstalling the program 'main.exe' ... :)
C# libraries can be installed with the CS.install_library function, and uninstalled with the CS.uninstall_library function.
Example:
def csharp_library_installation_and_uninstallation():
# Get and setup the C# compiler
csc = CS.get_default_compiler()
csc.debug = True
# Build the library
csc.build_shared_library('math_helper.dll', ['math_helper.cs'])
# Install the library
CS.install_library('math_helper.dll', 'libmath_helper')
# Uninstall the library
CS.uninstall_library('math_helper.dll', 'libmath_helper')
Example output:
Building C# shared library 'math_helper.dll' ...............................:\ warning CS8001: SDK path could not be resolved Installing the library 'math_helper.dll' ... :) Uninstalling the library 'math_helper.dll' ... :)
C# programs can be ran with the CS.run_print function.
Example:
def csharp_running_and_printing():
# Get and setup the C# compiler
csc = CS.get_default_compiler()
csc.debug = True
# Build the program
csc.build_program('main.exe', ['main.cs'])
# Run the C# program
csc.run_print('main.exe')
Example output:
Building C# program 'main.exe' .............................................:\ warning CS8001: SDK path could not be resolved Running C# program ... :) main.exe Hello World!
# Most of this section requires the modules:
import lib_raise_java as Java
Raise supports the OpenJDK 7 Java compiler. The compiler is abstracted away in a generalized way, as to make it so you don't have to worry about compiler specific functionality.
You can select the best Java compiler for your platform by using the Java.get_default_compiler function.
You can also select the compiler specifically by using the Java.cs_compilers dictionary. Be careful as only compilers that were found by Raise will be in the dictionary.
Example:
def java_compilers():
javac = Java.get_default_compiler()
# Print the compiler name and path for fun
print("name: {0}".format(javac._name))
print("path: {0} ".format(javac._path))
javac = Java.java_compilers['javac']
# Print the compiler name and path for fun
print("name: {0}".format(javac._name))
print("path: {0} ".format(javac._path))
Example output:
name: javac path: /usr/bin/javac name: javac path: /usr/bin/javac
After the compiler is selected, it can be configured using the properties.
Example:
def java_compiler_setup():
# Get a Java compiler
javac = Java.get_default_compiler()
# Compiler setup
javac.debug = True
javac.warnings = True
javac.verbose = False
javac.deprecation = True
# Print environmental variables to see what happens under the hood
print("$JAVAC: {0}".format(javac.javac))
print("$JAR: {0}".format(javac.jar))
print("$JAVA: {0}".format(javac.java))
print("$JAVAFLAGS: {0}".format(javac.javaflags))
Example output:
$JAVAC: javac $JAR: jar $JAVA: java $JAVAFLAGS: -g -deprecation
Java programs can be built using the Java.build_program function.
Example:
def java_building_program():
# Get and setup the Java compiler
javac = Java.get_default_compiler()
javac.debug = True
# Build the program
javac.build_program('main.class', ['main.java'])
Example output:
Building Java program 'main.class' ... :)
Java static library can be built using the Java.build_shared_library function.
Example:
def java_building_library():
# Get and setup the java compiler
javac = Java.get_default_compiler()
javac.debug = True
# Build the library
javac.build_jar('math_helper.jar', ['lib_math.java'])
Example output:
Building Java jar 'math_helper.jar' ... :)
Java programs can be installed with the Java.install_program function, and uninstalled with the Java.uninstall_program function.
Example:
def java_program_installation_and_uninstallation():
# Get and setup the Java compiler
javac = Java.get_default_compiler()
javac.debug = True
# Build the program
javac.build_program('main.class', ['main.java'])
# Install the program
Java.install_program('main.class', 'java_example')
FS.remove_binaries('main')
# Run the Java program from the system
#FIXME: Java.run_print does not work on Linux, because when installed it runs
# the app from a shell script that does "java blah".
#Java.run_print('main')
findlib.run_print("main")
# Uninstall the program
Java.uninstall_program('main.class', 'java_example')
Example output:
Building Java program 'main.class' ... :) Installing the program 'main.class' ... :) Removing binaries 'main' ... :) Running command ... :) main Hello World! Uninstalling the program 'main.class' ... :)
Java libraries can be installed with the Java.install_library function, and uninstalled with the Java.uninstall_library function.
Example:
def java_library_installation_and_uninstallation():
# Get and setup the Java compiler
javac = Java.get_default_compiler()
javac.debug = True
# Build the jar
javac.build_jar('lib_math.jar', ['lib_math.java'])
# Install the jar
Java.install_jar('lib_math.jar', 'lib_math')
# Uninstall the jar
Java.uninstall_jar('lib_math.jar', 'lib_math')
Example output:
Building Java jar 'lib_math.jar' ... :) Installing the jar 'lib_math.jar' ... :) Uninstalling the jar 'lib_math.jar' ... :)
Java programs can be ran with the Java.run_print function.
Example:
def java_running_and_printing():
# Get and setup the Java compiler
javac = Java.get_default_compiler()
javac.debug = True
# Build the program
javac.build_program('main.class', ['main.java'])
# Run the Java program
javac.run_print('main')
Example output:
Building Java program 'main.class' ... :) Running Java program ... :) java main Hello World!
# Most of this section requires the modules:
import lib_raise_process as Process
Raise normally runs events in serial. If you want to run events concurrently and leverage multiple CPU cores, you can use Process.concurrent_start and Process.concurrent_end. Make sure to only group the same type of events, between start and end. Otherwise it may give you unexpected results.
Example:
def concurrency():
# Get and setup the C compiler
cc = C.get_default_compiler()
cc.debug = True
# Tell Raise to start queueing the events after this function
Process.concurrent_start()
cc.build_object('main.o', ['main.c'])
cc.build_object('libexample.o', ['libexample.c'])
# Tell Raise to start running all the queued events concurrently
Process.concurrent_end()
Example output:
Building C objects concurrently ... 'main.o' ... :) 'libexample.o' ... :)
# Most of this section requires the modules:
import lib_raise_cpu as CPU
Information about the CPU can be gotten from properties:
Example:
def cpu():
print("Architechture: {0}".format(CPU.arch))
print("Bits: {0}".format(CPU.bits))
print("MHz: {0}".format(CPU.mhz))
print("Name: {0}".format(CPU.name))
print("Vendor Name: {0}".format(CPU.vendor_name))
print("Flags: {0}".format(str.join(', ', CPU.flags)))
print("Cores: {0}".format(CPU.cpus_total))
Example output:
Architechture: X86_64 Bits: 64 MHz: 2.8000 GHz Name: Intel(R) Pentium(R) CPU G640 @ 2.80GHz Vendor Name: GenuineIntel Flags: acpi, aperfmperf, apic, arat, arch_perfmon, bts, clflush, cmov, constant_tsc, cx16, cx8, de, ds_cpl, dtes64, dtherm, dts, eagerfpu, epb, ept, est, flexpriority, fpu, fxsr, ht, lahf_lm, lm, mca, mce, mmx, monitor, msr, mtrr, nonstop_tsc, nopl, nx, pae, pat, pbe, pcid, pclmulqdq, pdcm, pebs, pge, pln, pni, popcnt, pse, pse36, pts, rdtscp, rep_good, sep, ss, sse, sse2, sse4_1, sse4_2, ssse3, syscall, tm, tm2, tpr_shadow, tsc, tsc_deadline_timer, vme, vmx, vnmi, vpid, xsave, xsaveopt, xtopology, xtpr Cores: 2
If you choose to do development on Raise itself, there are some tools that can make it easier. These are located in the "tools" directory. These scripts are smart enough to automatically figure out the correct directories to work on. So you do not need to run them from the "tools" directory. Any directory will do.
If you make changes to the root "raise" file, you will want those same changes to be copied to all the other directories that have their own "raise" file (tests, docs, and examples). Instead of having to do this manually, you can use the "tools/update_raise_in_sub_directories.py" script. It will automatically look through all the sub directories and replace any files named "raise" with the root "raise" file.
python tools/update_raise_in_sub_directories.py