Showing posts with label llvm. Show all posts
Showing posts with label llvm. Show all posts

Tuesday, August 2, 2011

Makefile basics

By Rui Chen

--Makefile is really a broad topic, if need more, check the book Autotools.

Reading digest from Makefile tutorial(in Chinese)

每個Makefile中都應該寫一個清空目標文件(.o和執行文件)的規則,這不僅便於重編譯,也很利於保持文件的清潔。這是一個「修養」(呵呵,還記得我的《編程修養》嗎)。一般的風格都是:
clean:
 rm edit $(objects)
更為穩健的做法是:
.PHONY : clean
clean :
 -rm edit $(objects)
前面說過,.PHONY意思表示clean是一個「偽目標」,。而在rm命令前面加了一個小減號的意思就是,也許某些文件出現問題,但不要管,繼續 做後面的事。當然,clean的規則不要放在文件的開頭,不然,這就會變成make的默認目標,相信誰也不願意這樣。不成文的規矩是——「clean從來 都是放在文件的最後」。
上面就是一個makefile的概貌,也是makefile的基礎,下面還有很多makefile的相關細節,準備好了嗎?準備好了就來。

Part 2:
如果我們想定義一系列比較類似的文件,我們很自然地就想起使用通配符。make支援三個通配符:「*」,「?」和「~」。這是和Unix的B-Shell是相同的。
波浪號(「~」)字元在文件名中也有比較特殊的用途。如果是「~/test」,這就表示當前用戶的$HOME目錄下的test目錄。而 「~hchen/test」則表示用戶hchen的宿主目錄下的test目錄。(這些都是Unix下的小知識了,make也支援)而在Windows或是 MS-DOS下,用戶沒有宿主目錄,那麼波浪號所指的目錄則根據環境變數「HOME」而定。
通配符代替了你一系列的文件,如「*.c」表示所以後綴為c的文件。一個需要我們注意的是,如果我們的文件名中有通配符,如:「*」,那麼可以用轉義字元「\」,如「\*」來表示真實的「*」字元,而不是任意長度的字元串。


另給一個變數使用通配符的例子:
a. 列出一確定文件夾中的所有」.c"文件
objects := $(wildcard *.c)
b. 列出(a)中所有文件對應的".o"文件,在(c)中我們可以看到它是由make自動編譯出的。
$(patsubst %.c,%.o,$(wildcard *.c))
c. 由(a)(b)兩步,可寫出編譯並鏈接所有「.c"和」.o"文件
objects := $(patsubst %.c,%.o,$(wildcard *.c))
 foo : $(objects)
        cc -o foo $(objects)  
這種用法由關鍵字「wildcard」,「patsubst"指出,關於Makefile的關鍵字,我們將在後面討論。 


偽目標最早先的一個例子中,我們提到過一個「clean」的目標,這是一個「偽目標」,
clean:
 rm *.o temp
正像我們前面例子中的「clean」一樣,既然我們生成了許多文件編譯文件,我們也應該提供一個清除它們的「目標」以備完整地重編譯而用。 (以「make clean」來使用該目標)
因為,我們並不生成「clean」這個文件。「偽目標」並不是一個文件,只是一個標籤,由於「偽目標」不是文件,所以make無法生成它的 依賴關係和決定它是否要執行。我們只有通過顯式地指明這個「目標」才能讓其生效。當然,「偽目標」的取名不能和文件名重名,不然其就失去了「偽目標」的意 義了。
當然,為了避免和文件重名的這種情況,我們可以使用一個特殊的標記「.PHONY」來顯式地指明一個目標是「偽目標」,向make說明,不管是否有這個文件,這個目標就是「偽目標」。
.PHONY : clean
只要有這個聲明,不管是否有「clean」文件,要運行「clean」這個目標,只有「make clean」這樣。於是整個過程可以這樣寫:
.PHONY : clean
clean :
 rm *.o temp
偽目標一般沒有依賴的文件。但是,我們也可以為偽目標指定所依賴的文件。偽目標同樣可以作為「默認目標」,只要將其放在第一個。一個示例就是,如果 你的Makefile需要一口氣生成若干個可執行文件,但你只想簡單地敲一個make完事,並且,所有的目標文件都寫在一個Makefile中,那麼你可 以使用「偽目標」這個特性:




多目標Makefile的規則中的目標可以不止一個,其支援多目標,有可能我們的多個目標同時依賴於一個文件,並且其生成的命令大體類似。於是我們就能把 其合併起來。當然,多個目標的生成規則的執行命令不是同一個,這可能會可我們帶來麻煩,不過好在我們可以使用一個自動化變數「$@」(關於自動化變數,將 在後面講述),這個變數表示著目前規則中所有的目標的集合,這樣說可能很抽象,還是看一個例子吧。
bigoutput littleoutput : text.g
 generate text.g -$(subst output,,$@) > $@
上述規則等價于:
bigoutput : text.g
 generate text.g -big > bigoutput
littleoutput : text.g
 generate text.g -little > littleoutput
其中,-$(subst output,,$@)中的「$」表示執行一個Makefile的函數,函數名為subst,後面的為參數。關於函數,將在後面講述。這裏的這個函數是替換字元串的意思,「$@」表示目標的集合,就像一個數組,「$@」依次取出目標,並執于命令。


 This page is important to understand default variables.

我們可以把隱含規則中使用的變數分成兩種:一種是命令相關的,如「CC」;一種是參數相的關,如「CFLAGS」。下面是所有隱含規則中會用到的變數:
1、關於命令的變數。
AR
函數庫打包程式。默認命令是「ar」。
AS
彙編語言編譯程式。默認命令是「as」。
CC
C語言編譯程式。默認命令是「cc」。
CXX
C++語言編譯程式。默認命令是「g++」。
CO
從 RCS文件中擴展文件程式。默認命令是「co」。
CPP
C程式的預處理器(輸出是標準輸出設備)。默認命令是「$(CC) –E」。
FC
Fortran 和 Ratfor 的編譯器和預處理程式。默認命令是「f77」。
GET
從SCCS文件中擴展文件的程式。默認命令是「get」。
LEX
Lex方法分析器程式(針對於C或Ratfor)。默認命令是「lex」。
PC
Pascal語言編譯程式。默認命令是「pc」。
YACC
Yacc文法分析器(針對於C程式)。默認命令是「yacc」。
YACCR
Yacc文法分析器(針對於Ratfor程式)。默認命令是「yacc –r」。
MAKEINFO
轉換Texinfo源文件(.texi)到Info文件程式。默認命令是「makeinfo」。
TEX
從TeX源文件創建TeX DVI文件的程式。默認命令是「tex」。
TEXI2DVI
從Texinfo源文件創建軍TeX DVI 文件的程式。默認命令是「texi2dvi」。
WEAVE
轉換Web到TeX的程式。默認命令是「weave」。
CWEAVE
轉換C Web 到 TeX的程式。默認命令是「cweave」。
TANGLE
轉換Web到Pascal語言的程式。默認命令是「tangle」。
CTANGLE
轉換C Web 到 C。默認命令是「ctangle」。
RM
刪除文件命令。默認命令是「rm –f」。
2、關於命令參數的變數
下面的這些變數都是相關上面的命令的參數。如果沒有指明其默認值,那麼其默認值都是空。
ARFLAGS
函數庫打包程式AR命令的參數。默認值是「rv」。
ASFLAGS
彙編語言編譯器參數。(當明顯地調用「.s」或「.S」文件時)。
CFLAGS
C語言編譯器參數。
CXXFLAGS
C++語言編譯器參數。
COFLAGS
RCS命令參數。
CPPFLAGS
C預處理器參數。( C 和 Fortran 編譯器也會用到)。
FFLAGS
Fortran語言編譯器參數。
GFLAGS
SCCS 「get」程式參數。
LDFLAGS
鏈接器參數。(如:「ld」)
LFLAGS
Lex文法分析器參數。
PFLAGS
Pascal語言編譯器參數。
RFLAGS
Ratfor 程式的Fortran 編譯器參數。
YFLAGS
Yacc文法分析器參數。
==========
3、自動化變數
在上述的模式規則中,目標和依賴文件都是一系例的文件,那麼我們如何書寫一個命令來完成從不同的依賴文件生成相應的目標?因為在每一次的對模式規則的解析時,都會是不同的目標和依賴文件。
自動化變數就是完成這個功能的。在前面,我們已經對自動化變數有所提涉,相信你看到這裏已對它有一個感性認識了。所謂自動化變數,就是這種變數會把模式中所定義的一系列的文件自動地挨個取出,直至所有的符合模式的文件都取完了。這種自動化變數只應出現在規則的命令中。
下面是所有的自動化變數及其說明:
$@
表示規則中的目標文件集。在模式規則中,如果有多個目標,那麼,"$@"就是匹配于目標中模式定義的集合。
$%
僅當目標是函數庫文件中,表示規則中的目標成員名。例如,如果一個目標是"foo.a(bar.o)",那麼,"$%"就是 "bar.o","$@"就是"foo.a"。如果目標不是函數庫文件(Unix下是[.a],Windows下是[.lib]),那麼,其值為空。
$< 
依賴目標中的第一個目標名字。如果依賴目標是以模式(即"%")定義的,那麼"$<"將是符合模式的一系列的文件集。注意,其是一個一個取出來的。
$?
所有比目標新的依賴目標的集合。以空格分隔。
$^
所有的依賴目標的集合。以空格分隔。如果在依賴目標中有多個重複的,那個這個變數會去除重複的依賴目標,只保留一份。
$+
這個變數很像"$^",也是所有依賴目標的集合。只是它不去除重複的依賴目標。
$*
這個變數表示目標模式中"%"及其之前的部分。如果目標是"dir/a.foo.b",並且目標的模式是"a.%.b",那麼,"$*"的值就是"dir /a.foo"。這個變數對於構造有關聯的文件名是比較有較。如果目標中沒有模式的定義,那麼"$*"也就不能被推導出,但是,如果目標文件的後綴是 make所識別的,那麼"$*"就是除了後綴的那一部分。例如:如果目標是"foo.c",因為".c"是make所能識別的後綴名,所以," $*"的值就是"foo"。這個特性是GNU make的,很有可能不兼容於其它版本的make,所以,你應該盡量避免使用"$*",除非是在隱含規則或是靜態模式中。如果目標中的後綴是make所不 能識別的,那麼"$*"就是空值。
當你希望只對更新過的依賴文件進行操作時,"$?"在顯式規則中很有用,例如,假設有一個函數庫文件叫"lib",其由其它幾個object文件更新。那麼把object文件打包的比較有效率的Makefile規則是:
lib : foo.o bar.o lose.o win.o
           ar r lib $?
在上述所列出來的自動量變數中。四個變數($@、$<、$%、$*)在擴展時只會有一個文件,而另三個的值是一個文件列表。這七個自動化變數 還可以取得文件的目錄名或是在當前目錄下的符合模式的文件名,只需要搭配上"D"或"F"字樣。這是GNU make中老版本的特性,在新版本中,我們使用函數"dir"或"notdir"就可以做到了。"D"的含義就是Directory,就是目錄,"F"的 含義就是File,就是文件。

Saturday, July 30, 2011

llvm patched with systemc library

By Rui Chen

In this article, I will get into the IR generated by the llvm-g++ along with the systemc library.

Understand the installation flow of PinaVM
The project is to mimic the idea of PinaVM, but I have to repeat the first few steps to understand the relationship between llvm-g++ and systemc library. Check out the /doc/install document for details.

One limit is that you have to use LLVM 2.6, which may suffer incompatible features with the latest version.

Start from autoconf part, which is Step 3 in the manual
1. autoconf
What the autoconf do is to seek a file named configure.ac (or configure.in for backward compatibility), and then runs the M4 macro processor to create the configure script.

2. configrue
command ./configure --with-tools-dir=$DOWNLOAD
Part of the output:
configure: Summary of variables:

DOWNLOAD_AND_COMPILE_DIR: /home/chenrui/Desktop/pinavm/download
INSTALL_PATH_LLVM: /home/chenrui/Desktop/pinavm/lib/llvm-2.7
INSTALL_PATH_LLVMGCC: /home/chenrui/Desktop/pinavm/lib/llvm-gcc
INSTALL_PATH_SYSTEMC_LLVM: /home/chenrui/Desktop/pinavm/lib/systemc-2.2.0-llvm
INSTALL_PATH_SYSTEMC_GCC: /home/chenrui/Desktop/pinavm/lib/systemc-2.2.0-gcc

configure: creating ./config.status
config.status: creating config.mk
config.status: creating config.sh
The code in the configure.ac file:
DOWNLOAD_AND_COMPILE_DIR="${TOOLS_DIR}/download"
INSTALL_PATH_LLVM=${TOOLS_DIR}/lib/llvm-2.7
INSTALL_PATH_LLVMGCC=${TOOLS_DIR}/lib/llvm-gcc
INSTALL_PATH_SYSTEMC_LLVM=${TOOLS_DIR}/lib/systemc-2.2.0-llvm
INSTALL_PATH_SYSTEMC_GCC=${TOOLS_DIR}/lib/systemc-2.2.0-gcc
So the "--with-tools-dir" means specifying the $DOWNLOAD directory for ${TOOLS_DIR}.

Another part of configure.ac:
# Defining files to be generated
AC_CONFIG_FILES([config.mk
                 config.sh])
Then config.mk and config.sh will be generated.
NOTE: normally, AC_CONFIG_FILES([Makefile]) is used(ref link).

Motivation to use SystemC and LLVM
I have done a simple literal translator with SystemC-to-VHDL translator with ANTLR, and I think it needs tremendous effort to crack the whole C++ grammar.
Besides, sc2v and gsc and many tools are based on their self-made compilers, which suffers a severe issue that only a small set of systemc grammar can be compiled.

Based on this understanding, it is very important to immigrate the translation method from ANTLR literal way to llvm-g++ based.


Generate simple backend first.
Another idea about working with C++ & Systemc with LLVM is that I can generate a VHDL experiment backend for test first and then connect it to the systemc frontend.

Friday, July 29, 2011

systemc: form installation to run

By Rui Chen

My OS is Ubuntu 11.04, and the installed systemc is 2.2.0.

Here are the command lines to install the package:
1. Goto the OSCI website, and download the latest package.
2. Create a separate folder named /usr/local/systemc-2.2
3. Go seeking the cpp file with the directory like  systemc-2.2.0/src/sysc/utils/sc_utils_ids.cpp, and then add two statements into the file:
#include "string.h"
#include "cstdlib"
using namespace std;
4. Go to the systemc-2.2 folder, and type
xx/systemc-2.2.0/configure
sudo make
sudo make install
The separate installation folder can also avoid the name collision if installation conducted in the same folder.

Verification of the installation
The example file is adopted here(ref), while the command line doesn't work, even the echo $SYSTEMC_HOME didn't show the directory for systemc.
So, I change the command to the absolute address as shown below:


reference for running the systemc program
http://linuxhao.com/Linux/doc/Linux_doc.asp?id=2938
If we change all the addresses to the absolute ones, then we can make it. The final command lines are below:
export SYSTEMC=/home/chenrui/Desktop/llvm/systemc-2.2.0 # chenrui is my computer name, I have checked that the systemc.h is in the systemc-2.2.0 folder.
g++ -I $SYSTEMC/include -L $SYSTEMC/lib-linux -o example.o example.cpp -lsystemc -lm
Besides, I have also changed the line 2 of example.cpp so that I can find the systemc library.
And then, it is pretty sure that you can "Hello World." output.

What a wonderful day.

Wednesday, April 6, 2011

llvm搭建平台-2

Rui Chen
04-07

昨天说没有平台问题,现在看来,这句话有误. 而反观今天的所作所为却又是扰了一个大圈子,不过linux也够有内容,而linux的跨版本升级也不是得心应手。所以,最好走的是降格以求的路线,因为事实上,llvm-gcc是解压后,放到/usr/local中去的。所以,总结起来就是重新下载llvm-gcc 2.6 front end 即可。而lli也再没有这种不匹配的情况。

llvm-gcc --version后的结果
llvm-gcc (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2.8)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

llvmc --version后的结果,llvmc是llvm的指令
  llvm version 2.7 ( 2.7-0ubuntu1)
  Optimized build.
  Built Apr 28 2010 (14:16:19).
  Host: i386-pc-linux-gnu
  Host CPU: k8-sse3

  Registered Targets:
    (none)

这是小电脑上的结果,当然这里也有相关的讨论,llvm 2.6的版本是Built Jul 24 2010(08:41:55). 现在的解决思路就是重新build llvm2.8了.

问题解决的时候还有插曲
rui@ubuntu:~$ sudo apt-get install ubuntu
apt-get: /usr/local/lib/libstdc++.so.6: version `GLIBCXX_3.4.11' not found (required by apt-get)
apt-get: /usr/local/lib/libstdc++.so.6: version `GLIBCXX_3.4.11' not found (required by /usr/lib/libapt-pkg-libc6.10-6.so.4.8)
解决的链接在此. 相关文章(link),but for GLIBCXX_3.4.9
--
同样的问题居然出现了两次,上面的解决链接这次就没有作用了,新的参考ref(桌面没有图标,还需要mark一下),其他人的一些讨论(link),引我到那个ref上的, 当然,我本着只是解决问题的目的, 更多关于Linux库文件的讲解,在此先做个标记(link1(linux处理库文件路径), link2(关于gcc和libstdc++))
--
Similar solution code(revision needed):
cd /opt/openoffice.org3/basis-link/ure-link/lib

sudo mv libstdc++.so.6 libstdc++.so.6.orig
sudo ln -s /usr/lib/libstdc++.so.6.0.9 libstdc++.so.6

sudo mv libgcc_s.so.1 libgcc_s.so.1.orig
sudo ln -s /lib/libgcc_s.so.1



关于ubuntu的ISO升级方式
参考资料:ref1, ref2, ref3
ref1 太过粗浅, ref2结尾的一句必须要注意(当然我也在上面吃了亏),必须要是发行版,而不能是beta版, ref3有作者的一些经历.
软件下载来之后,先md5sum看看有没有问题, 官网上面有对比值: 10.04-lucid, 11.04-natty.
使用指令md5sum ubuntu-10.04.2-alternate-i386.iso(后面的文件名相应修改)(md5介绍ref,另一个ref(没有参考))安装升级,这篇是精华文章link, 它也同样指出ubuntu的跨版本支持并不好.

继续往下走,小电脑又有了问题,没有/media/cdrom/.(注: /media/cdrom0实际上就是一个虚拟的挂载对象,可以在任何路径下设置这个cdrom0的空文件夹) .
其中,还有使用到su(指令su ,切换到root权限,但是总是su: Authentication failure, sudo passwd,然后用这个新密码就好了!)
似乎,没有cd-rom就是一个很大的bug,因此,放弃在ubuntu下ISO离线升级的方式.

常用指令(link) ,check ubuntu 版本:
cat /etc/issue
或 cat /etc/lsb-release 
或 lsb_release -dsc


link是ubuntu中文社区所有的文章聚合。
里面又有提到,版本需要step by step的升级。
ref(for 10.04 to 10.10):从1004升级,你应该先dist-upgrade一次,保证软件都正确了,再update-manager -d。