Sunday, May 22, 2011

Compiling and linking with Makefile


This entire article is INVALID since the go command was released. This page is being retained only for historic reasons.


During programming one has to repeatedly compile and link the source code, You can use the separate compile and link method we have been using so far - i.e. running 8g or 6g on the .go file, then running 8l or 6l on the output file generated by the previous step. This method gets unwieldy as we progress on to larger projects involving multiple files and multiple teams working together on it. One of the programmer’s solutions for that is to do a make. The go version of it is called gomake.

The Makefile is a definition of what files to include in the compilation and linking process and what to name the output file. Here is an example that I have.

Filename: Makefile
include ${GO_HOME}/go/src/Make.inc

TARG=hello

GOFILES=\
        hello.go\

include ${GO_HOME}/go/src/Make.cmd

There are only a few lines in this Makefile and it might seem superfluous at the moment, but as your project grows you can continue to add to this incrementally and ease the management of the compiling and linking process.

include ${GO_HOME}/go/src/Make.inc
include ${GO_HOME}/go/src/Make.cmd
These are two required lines that references files that the make process requires. GO_HOME is an environment variable I have defined to point to the folder where go has been installed. I have set it as an entry in my ~/.bashrc file as export GO_HOME=~/coding/go. Since I use bash as my shell, it will set this value each time I login. I suggest you do this too. That way when you share development with others, irrespective of the folder in which you have installed go, your programs will compile properly. Also, there is less to remember and rewrite each time.

TARG=stringtests_out defines the executable file that is created at the end of make’s compilation and linking. You could name it what you want as long as you follow Unix’s file naming conventions. Typically though, they do not have extensions like .exe that one finds in Windows.

GOFILES=\
hello.go\

This sections defines the input files that will be used for compilation.

To compile and link using the make process for this is fairly simple. Go to the directory where the Makefile is and run the gomake command.

cmd-prompt> gomake
8g -o _go_.8 hello.go
8l -o hello_out _go_.8
cmd-prompt> ./hello
Hello World!
cmd-prompt>


By default, gomake picks up a file named Makefile to work on. As you can see, it has picked the appropriate compiler and linker and done its work to produce the executable file that you had specified.

The make process recognizes if there have been any changes to the source file and will not run the process a second time if there aren’t any changes. If you ran gomake twice repeatedly, it would return immediately with this error.

make: Nothing to be done for `Makefile'.

You may also rename the Makefile to whatever you want as long as you follow Unix naming conventions. But if you call it anything other than that, pass it as a parameter to gomake.

gomake -f myFileForMake

The two files Make.inc and Make.cmd that you have referenced in your Makefile are normal text files. Don’t make any changes to them if you want your compiling and linking to go well, but you are always free to read them. The include command combines the content of those files into your own Makefile. Therefore, there is free functionality that you can call up. One common thing to do is a clean, which removes all the temporary files and other files generated in previous compilation and linking. After doing this, you can do a new gomake. Before, we get to the cleaning, let’s do an example where I explain a target. Create a Makefile as below.

Full file: Makefile
include ${GO_HOME}/go/src/Make.inc

include ${GO_HOME}/go/src/Make.cmd

mytarget: my_sub_target
 echo "This is within the target mytarget"

my_sub_target:
 echo "This is within the target my_sub_target"

In the Makefile above, mytarget and my_sub_target are targets. When executing the contents of the file, I can specify a particular target that I want to execute. Let’s try it and see what happens.

gomake mytarget
echo "This is within the target my_sub_target"
This is within the target my_sub_target
echo "This is within the target mytarget"
This is within the target mytarget

We instructed that mytarget should be run, but it has first run my_sub_target and then mytarget. This is because we have specified that there is a dependency on this line: mytarget: my_sub_target
. This line indicates that if mytarget is executed, then my_sub_target should be executed first.

Now let’s look at the clean target again. It is currently not there in your Makefile, but since it is there in some files that you included, you can still do it as shown below.

Filename: Makefile
include ${GO_HOME}/go/src/Make.inc

TARG=hello

GOFILES=\
        hello.go\

include ${GO_HOME}/go/src/Make.cmd

gomake clean

rm -rf *.o *.a *.[568vq] [568vq].out hello _test _testmain.go

That should clean out all the temporary files that were generated previously. Another useful target you could create is to automatically format your code using the go formatting tool gofmt. Here is a sample of the Makefile with a format target.

Filename: Makefile
include ${GO_HOME}/go/src/Make.inc

TARG=hello

GOFILES=hello.go

include ${GO_HOME}/go/src/Make.cmd

format:
 gofmt -w hello.go

You can compile and link the file with:
gomake
and format the code with
gomake format.

You can read further about make files on the net and learn how to use variable names within the file. This will allow you to more easily maintain the file and your compilation and linking process. Here is an example, where the source file is listed in a variable, SRC, and it is reused in a couple of places.

Filename: Makefile
include ${GO_HOME}/go/src/Make.inc

TARG=hello
GOFMT=gofmt

SRC=hello.go

GOFILES=${SRC}

include ${GO_HOME}/go/src/Make.cmd

format:
 ${GOFMT} -w ${SRC}


No comments:

Post a Comment

If you think others also will find these tutorials useful, kindly "+1" it above and mention the link in your own blogs, responses, and entries on the net so that others also may reach here. Thank you.

Note: Only a member of this blog may post a comment.