This topic was published by DevynCJohnson and viewed 779 times since "". The last page revision was "".
- Topics - 444
Many developers use Linux. Considering that Linux itself and nearly all of the software is open source (unless the user installs proprietary software), software development is important to the Linux community. One of the most important parts of programming is the compiler. A compiler gets the code and creates the final product. This final object may be an executable file, a library, driver, etc. Compilers use linkers to connect generated object files, parsers check the code for errors, etc. There are may steps involved in compiling code. However, the purpose of this article is to understand how a programmer would use a compiler, the types of compilers, and what compilers are available for Linux.
In simple terms, a compiler typically converts higher-level programming languages to a lower-level languages. For example, many C/C++ compilers get C/C++ code and create an executable that contains machine-code (which is more low-level than assembly).
A decompiler converts a low-level language (such as machine-code) to a higher-level languages (like assembly or C/C++).
A cross-compiler creates machine code for a different machine.
A rewriter changes some expressions, commands, symbols, etc. in the source code, but the source code is still the same language.
The GNU Toolchain is a popular development suite containing many tools. A subset of this toolchain is called the GNU Compiler Collection and it contains some compilers. "gcc" (lowercase letters) is the compiler for C code and g++ compiles C++ code. The compilers in the GNU Compiler Collection (like most compilers) are not single programs. Rather, the g++ compiler is a frontend that informs the GNU Toolchain that C++ code is intended to be compiled. The system has a default linker, parser, assembler, lexer, etc. that it will use. However, the user may install other tools and use parameters in the command-line to specify which tools should be used.
The basic usage of the GNU compilers looks like this - "g++ -c myprog.cpp". That command compiles the specified C++ source code file to an object file. Next, type "g++ -o ./Program ./myprog.o" which will perform some more actions to create the final program, designated as "-o ./Program". Many other parameters exist which can specify many different behaviors and outcomes. For instance, to include certain libraries or indicate the location of certain libraries, use the "-I" parameter for each specified path. For instance, "g++ -I/usr/lib/include/my-libs -c myprog.cpp" is a suitable example. Notice that there is no space between the "-I" parameter and the path. Many (or most) compilers use such a format.
Some other GNU compiler wrappers are available. The "Go" programming language is compiled with gogcc, and Java is compiled to class files with gcj. Other supported wrappers include gdc (D), ghc (Haskell), ghdl (vhdl), gpc (Pascal), gnat (Ada), gfortran (Fortran), g77 (deprecated Fortran compiler), gobjc (Objective-C), and JGNAT (Ada to Java bytecode).
NOTE: ghc = Glasgow Haskell Compiler
The GNU Compiler Collection supports more languages than mentioned. To compile such languages, test if "gcc" supports the language already without needing a wrapper or special parameter. If not, than install any needed libraries, extensions, compilers, wrappers, etc. Also, be aware if the language must be specified via a parameter. For example, to compile Objective-C with gcc, type a command similar to any of the commands below.
gcc -c prog.m gcc -lobjc -o Program prog.m
JGNAT is a form of GNAT that compiles Ada to Java Bytecode. Another form of GNAT includes "GNAT for dotNET" which compiles Ada for the .NET Framework.
NOTE: The GNU Interpreter for Java (GIJ) is an interpreter for Java bytecode. This program is not a compiler.
Gambas is a form of BASIC. Gambas and its IDE (under the same name) resemble Visual Basic and Microsoft's standard Visual Basic IDE. The Gambas compiler for the command-line is "gbc3".
Clang is a C/C++ and Objective C/C++ compiler that uses LLVM as its backend. Clang is a comparable alternative to GCC. LLVM (Low Level Virtual Machine) manages the optimizations and various other tasks.
Vala developers using GTK as the GUI may find "gtkamlc" helpful. "gtkamlc" is a compiler for both the GtkON language and the Gtkaml language. With these languages and the compiler, the GTK code will be compact in the Vala program.
Numerous other compilers are available for Linux for a variety of programming languages. Some are seen below.
- valac - Vala
- booc - Boo
- llc - LLVM Compiler for LLVM bitcode/bytecode (*.bc) or LLVM assembly (*.ll)
- mcs - Mono C#
- luac - Compiler Lua to bytecode
- javac - Compile Java files (*.java) to Java class files (*.class)
- gcl - Common Lisp
- wxrc - WxWidget XML compiler
- ocamlc - Ocaml
- groovyc - Groovy
- cxfreeze - Python; create stand-alone binary executables from scripts written in Python.
- Nuitka - Python compiler
- scalac - compile Scala to Java bytecode (class files)
License Compiler (Mono)
"lc" is a license compiler for the Mono framework. Mono is a framework that provides the .NET Framework, the Common Language Runtime virtual/runtime machine, and C# tools to Linux, BSD, Solaris, and other systems. The license compiler allows a software license (as "licenses.licx") for proprietary code to be embedded into the program that will be compiled. For illustration, a software developer may write a program in .NET using Mono on a Linux system. The developer intends to sell the program. The license agreement (like the EULA licenses common to Windows) is then created as a "licenses.licx", and "lc" compiles the file. Then, when the whole program is to be compiled, the compiler will get the file create by "lc".
Some special wrappers exist for GCC. For example, "c89" is a wrapper (in the form of a script) that calls "gcc" and specifies that the C89 standard be used. Other wrappers include c99 (C99 standard), f95 (Fortran 95), and others. Wrappers serve as shortcuts. Instead of typing parameters or knowing the full name of a cross-compiler (like "arm-linux-androideabi-*"), users can type a command that is easier to remember.
Programmers could make their own wrappers if needed. To make a wrapper, create a simple shell script. For illustration, Android developers may make a wrapper for the Android cross-compiler for ARM devices to compile C++ code (arm-linux-androideabi-g++). In the script, a hashpling is needed (#!/bin/sh). Next, include this line - "arm-linux-androideabi-g++ HARD-CODED-PARAMS $@". The programmer can include hard-coded parameters that are always needed like include parameters (-I) for Android libraries. The "$@" is a variable representing all of the parameters given to the wrapper. Lastly, save and name the script. A name like "droidc" would be suitable. Place the script in the system's executable path (like /usr/bin/ as listed in $PATH) and give the script executable permissions (chmod +x /usr/bin/droidc). To use the wrapper, type something like "droidc -c app.cpp". Doing so is equivalent to typing "arm-linux-androideabi-g++ -O2 -I/usr/lib/my/android/libs -Wall -c app.cpp". The wrapper can also include other commands if needed.
To cross-compile using gcc, the developer can use "arm-linux-androideabi-gcc" instead of "gcc" to cross-compile for Android running on ARM. Alternately, add "--toolchain=arm-linux-androideabi" as a parameter to the "gcc" command to achieve the same results. Again, the developer could also type "--arch=arm" to cross-compile to ARM.
Programmers can also use Clang via gcc to cross-compile code. For instance, to cross-compile through Clang via gcc, the parameter is "--toolchain=arm-linux-androideabi-clang3.3" or "--arch=arm –llvm-version=3.3".
Interestingly, programmers can call Clang directly and use parameters to use gcc under Clang to compile the code - "-target armv5te-none-linux-androideabi -gcc-toolchain $NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64".
MinGW (Minimalist GNU for Windows) is a cross-compiler that is used to make Windows applications. MinGW uses a port of the GNU compiler collection, thus MinGW supports C/C++, Objective C/C++, Ada, and Fortran. MinGW supports compiling 32 and 64-bit programs for Windows systems, as long as the system has the needed compilers and libraries. The MingGW compiler interfaces with the GNU Compiler Collection, thus allowing users to use similar commands and parameters to cross-compile the code for Windows as a developer would for compiling Linux programs. For example, to cross-compile C++ code with MinGW for an i586 Windows machine, try using the command below.
i586-mingw32msvc-g++ -c prog.cpp i586-mingw32msvc-g++ -o Program.exe prog.o
# To disassemble:
i586-mingw32msvc-objdump -x Program.exe
For a 64-bit Windows machine, replace "i586-mingw32msvc" with "x86_64-w64-mingw32" and remember to change any parameters and libraries as needed.
On most systems, users can type "ls /usr/" and see some of the directories containing cross-compilers. Remember, /usr/ is a directory that contains some common and essential directories like /usr/bin/ and /usr/share/. Not everything in /usr/ is a cross-compiler. The user is looking for directories that look like one of the following below. Keep in mind that other cross-compilers exist other than the listed below.
For each of these cross-compilers, the common command-line usage look like this - "powerpc-linux-gnu-gcc PARAMS". If cross-compiling C++ to PowerPC, try "powerpc-linux-gnu-g++", or for Fortran "powerpc-linux-gnu-gfortran".
Below are some sample commands for transcompilation and other helpful tricks. The octothorpes/pound-signs (#) are comments, not code that is usable.
- # C/C++ => LLVM Bytecode
- # *.c/*.cpp => *.ll (LLVM IR file)
- clang -S -emit-llvm FILE.c
- # LLVM Bytecode => LLVM Assembly
- # *.ll => *.s
- llc FILE.ll
- # Compile C/C++ via LLVM bytecode
- clang -emit-llvm -o foo.bc -c foo.c
- clang -o foo foo.bc
- NOTE: A LLVM Bytecode file (*.bc) is the same as a LLVM Object file (*.o).
- # LLVM Bytecode => C/C++
- llc -march=c -o code.c code.ll # C
- llc -march=c++ -o code.cpp code.ll # C++
- # *.c/*.cpp => a.out.js
- emcc FILE.cpp
- # run "node a.out.js" to test the file
- # Python script => Python Bytecode
- python -m py_compile SCRIPT.py # Python2 .pyc
- python -OO -m py_compile SCRIPT.py # Python2 .pyo
- python3 -m py_compile SCRIPT.py # Python3 .pyc
- python3 -OO -m py_compile SCRIPT.py # Python3 .pyo
- # Python Script => C/C++
- cython SCRIPT.py # Python2 to C
- cython --cplus SCRIPT.py # Python2 to C++
- cython -3 SCRIPT.py # Python3 to C
- cython -3 --cplus SCRIPT.py # Python3 to C++
- # Python to Stand-alone binary executable
- cxfreeze SCRIPT.py # Python2
- cxfreeze3 SCRIPT.py # Python3
- cxfreeze3 -OO SCRIPT.py # Python3 Optimized
NOTE: Some of you may be wondering why the above example is using cxfreeze3 (which is for Python3 scripts) despite the fact that most (or all) repos lack cxfreeze3. A cxfreeze version for Python3 has been released, but the source code does not compile correctly. I got the source code and fixed the bug. I now have a perfectly working copy of cxfreeze3 that produces Python3-based stand-alone executables that execute very well. If you would like cxfreeze3 on your system, read the directions near the end of this article. If needed, email me and I will send you the fix for the bug and directions for installation.
For those of you wanting to learn how to use a compiler mentioned in this article, checkout these links. However, this is not a complete list.
- Booc: (http://boo.codehaus.org/Boo+Compiler) | (http://boo.codehaus.org/How+To+Compile)
- GCC: PDF(www.gnu.org/s/gnu-c-manual/gnu-c-manual.pdf) | Many_goodies(https://gcc.gnu.org/onlinedocs/)
- Groovyc: http://groovy.codehaus.org/The+groovyc+Ant+Task
- Gtkamlc: (http://dev.man-online.org/man1/gtkamlc/) | (https://code.google.com/p/gtkaml/)
- LLVM: http://llvm.org/docs/CommandGuide/index.html
- luac: http://www.lua.org/manual/5.2/luac.html
- Nuitka: http://nuitka.net/
- Scalac: http://www.scala-lang.org/files/archive/nightly/docs-2.10.2/manual/html/scalac.html
- Valac: (http://linux.die.net/man/1/valac) | (https://wiki.gnome.org/Projects/Vala/Tutorial)
CxFreeze for Python3
This section just pertains to developers wanting cxfreeze for Python3. Most readers can skip this section.
Running "pip install cx_Freeze" in a command-line installs cxfreeze for Python2. Using "pip3" instead of "pip" will show an error with setting up cxfreeze for Python3. However, cxfreeze can still be obtained. I have tested these directions successfully using cxfreeze 4.3.3.
2. View the code for the "setup.py"
3. Go to line 80
4. Depending on the version of cxfreeze obtained, the line "if not vars.get("Py_ENABLE_SHARED", 0):" will be line number 80 or 81 (possibly even somewhere between 76-85).
HINT: The line before it is "vars = distutils.sysconfig.get_config_vars()".
5. Once found, replace "if not vars.get("Py_ENABLE_SHARED", 0):" with "if True:". Do not change the indent from the original layout.
6. Save and close the file.
7. Continue to install cxfreeze using the setup.py file as normal.
8. To use cxfreeze3 from a command-line, create a file named "cxfreeze3" and put in the code below (it is just three lines of code). Remember to save and close the file.
#!/usr/bin/env python3 from cx_Freeze import main main()
9. Make the new script executable (IN-THE-SHELL:$ chmod +x cxfreeze3).
10. Place the script in /usr/bin/ or some other preferred path location using Root privileges (SHELL:$ cp cxfreeze3 /usr/bin/cxfreeze3).