Typical USB 2.0 Sequence
The steps below are a typical sequence of events that occurs during enumeration of a USB 2.0 device under Windows. Device firmware shouldn’t assume that enumeration requests and events will occur in a particular order. To function successfully, a device must detect and respond to any control request or other bus event at any time.
1. The system has a new device. A user attaches a device to a USB port, or the system powers up with a device attached. The port may be on the root hub at the host or on a hub that connects downstream from the host. The hub provides power to the port, and the device is in the Powered state. The device can draw up to 100 mA from the bus.
2. The hub detects the device. The hub monitors the voltages on the signal lines (D+ and D-) at each of its ports. The hub has a pull-down resistor of 14.25k–24.8kW on each line. A device has a pull-up resistor of 900–1575W on D+ for a full-speed device or D- for a low-speed device. High-speed-capable devices attach at full speed. On attaching to a port, the device’s pull-up brings its line high, enabling the hub to detect that a device is attached. On detecting a device, the hub continues to provide power but doesn’t yet transmit USB traffic to the device. Chapter 15 has more on how hubs detect devices.
3. The host learns of the new device. Each hub uses its interrupt endpoint to report events at the hub. The report indicates only whether the hub or a port (and if so, which port) has experienced an event. On learning of an event, the host sends the hub a Get Port Status request to find out more. Get Port Status and the other hub-class requests described are standard requests that all hubs support. The information returned tells the host when a device is newly attached.
4. The hub detects whether a device is low or full speed. Just before resetting the device, the hub determines whether the device is low or full speed by examining the voltages on the two signal lines. The hub detects the device’s speed by determining which line has a higher voltage when idle. The hub sends the information to the host in response to the next Get Port Status request. A USB 1.x hub may instead detect the device’s speed just after a bus reset. USB 2.0 requires speed detection before the reset so the hub knows whether to check for a high-speed-capable device during reset as described below.
5. The hub resets the device. When a host learns of a new device, the host sends the hub a Set Port Feature request that asks the hub to reset the port. The hub places the device’s USB data lines in the Reset condition for at least 10 ms. Reset is a special condition where both D+ and D- are logic low. (Normally, the lines have opposite logic states.) The hub sends the reset only to the new device. Other hubs and devices on the bus don’t see the reset.
6. The host learns if a full-speed device supports high speed. Detecting whether a device supports high speed uses two special signal states. In the Chirp J state, only the D+ line is driven and in the Chirp K state, only the D- line is driven.
During the reset, a device that supports high speed sends a Chirp K. A high-speed-capable hub detects the Chirp K and responds with a series of alternating Chirp K and Chirp J. On detecting the pattern KJKJKJ, the device removes its full-speed pull-up and performs all further communications at high speed. If the hub doesn’t respond to the device’s Chirp K, the device knows it must continue to communicate at full speed. All high-speed devices must be capable of responding to control requests at full speed.
7. The hub establishes a signal path between the device and the bus. The host verifies that the device has exited the reset state by sending a Get Port Status request. A bit in the returned data indicates whether the device is still in the reset state. If necessary, the host repeats the request until the device has exited the reset state.
When the hub removes the reset, the device is in the Default state. The device’s USB registers are in their reset states, and the device is ready to respond to control transfers at endpoint zero. The device communicates with the host using the default address of 00h.
8. The host sends a Get Descriptor request to learn the maximum packet size of the default pipe. The host sends the request to device address 00h, endpoint zero. Because the host enumerates only one device at a time, only one device will respond to communications addressed to device address 00h even if several devices attach at once.
The eighth byte of the device descriptor contains the maximum packet size supported by endpoint zero. A Windows host requests 64 bytes but after receiving just one packet (whether or not it has 64 bytes), the host begins the Status stage of the transfer. On completing the Status stage, Windows requests the hub to reset the device as in step 5 above. The USB 2.0 specification doesn’t require a reset here. The reset is a precaution that ensures that the device will be in a known state when the reset ends.
9. The host assigns an address. When the reset is complete, the host controller assigns a unique address to the device by sending a Set Address request. The device completes the Status stage of the request using the default address and then implements the new address. The device is now in the Address state. All communications from this point on use the new address. The address is valid until the device is detached, a hub resets the port, or the system reboots. On the next enumeration, the host may assign a different address to the device.
10. The host learns about the device’s abilities. The host sends a Get Descriptor request to the new address to read the device descriptor. This time the host retrieves the entire descriptor. The descriptor contains the maximum packet size for endpoint zero, the number of configurations the device supports, and other basic information about the device.
The host continues to learn about the device by requesting the one or more configuration descriptors specified in the device descriptor. A request for a configuration descriptor is actually a request for the configuration descriptor followed by all of its subordinate descriptors up to the number of bytes requested. A Windows host begins by requesting just the configuration descriptor’s nine bytes. Included in these bytes is the total length of the configuration descriptor and its subordinate descriptors.
Windows then requests the configuration descriptor again, this time requesting the number of bytes in the retrieved total length. The device responds by sending the configuration descriptor followed by all of the configuration’s subordinate descriptors, including interface descriptor(s), with each interface descriptor followed by any endpoint descriptors for the interface. Some configurations also have class- or vendor-specific descriptors. This chapter has more on what the descriptors contain.
11. The host assigns and loads a device driver (except for composite devices). After learning about a device from its descriptors, the host looks for the best match in a driver to manage communications with the device. Windows hosts use INF files to identify the best match. The INF file may be a system file for a USB class or a vendor-provided file that contains the device’s Vendor ID and Product ID. Chapter 9 has more about selecting a driver.
For devices that have been enumerated previously, Windows may use stored information instead of searching the INF files. After the operating system assigns and loads the driver, the driver may request the device to resend descriptors or send other class-specific descriptors.
An exception to this sequence is composite devices, which can have different drivers assigned to multiple interfaces in a configuration. The host can assign these drivers only after enabling the interfaces, so the host must first configure the device as described below.
12. The host’s device driver selects a configuration. After learning about a device from the descriptors, the device driver requests a configuration by sending a Set Configuration request with the desired configuration number. Many devices support only one configuration. If a device supports multiple configurations, the driver can decide which configuration to request based on information the driver has about how the device will be used, or the driver can ask the user what to do or just select the first configuration. (Many drivers only select the first configuration.) On receiving the request, the device implements the requested configuration. The device is now in the Configured state and the device’s interface(s) are enabled.
For composite devices, the host can now assign drivers. As with other devices, the host uses the information retrieved from the device to find a driver for each active interface in the configuration. The device is then ready for use.
Hubs are also USB devices, and the host enumerates a newly attached hub in the same way as other devices. If the hub has devices attached, the host enumerates these after the hub informs the host of their presence.
Attached state. If the hub isn’t providing power to a device’s VBUS line, the device is in the Attached state. The absence of power may occur if the hub has detected an over-current condition or if the host requests the hub to remove power from the port. With no power on VBUS, the host and device can’t communicate, so from their perspective, the situation is the same as when the device isn’t attached.
Suspend State. A device enters the Suspend state after detecting no bus activity, including SOF markers, for at least 3 ms. In the Suspend state, the device should limit its use of bus power. Both configured and unconfigured devices must support this state. Chapter 16 has more about the Suspend state.
Tuesday, November 9, 2010
Wednesday, October 20, 2010
Things to know of spinlocks
Spin locks can be used in interrupt handlers, whereas semaphores cannot be used because they sleep
If a lock is used in an interrupt handler, you must also disable local interrupts (interrupt requests on the current processor) before obtaining the lock
So the pseudo code of spin lock
{
Disable preempt()
acquire_lock()
}
If used in ISR
{
Disable interrupts()
spin lock()
//critical region
spin_unlock()
}
OR
{
spinlock_t mr_lock = SPIN_LOCK_UNLOCKED;
unsigned long flags;
spin_lock_irqsave(&mr_lock, flags);
/* critical region ... */
spin_unlock_irqrestore(&mr_lock, flags);
}
The fact that a contended spin lock causes threads to spin (essentially wasting processor time) while waiting for the lock to become available is important. This behavior is the point of the spin lock. It is not wise to hold a spin lock for a long time. This is the nature of the spin lock: a lightweight single-holder lock that should be held for short durations. An alternative behavior when the lock is contended is to put the current thread to sleep and wake it up when it becomes available. Then the processor can go off and execute other code. This incurs a bit of overhead most notably the two context switches required to switch out of and back into the blocking thread, which is certainly a lot more code than the handful of lines used to implement a spin lock. Therefore, it is wise to hold spin locks for less than the duration of two context switches. Because most of us have better things to do than measure context switches, just try to hold the lock as little time as possible[1]. The semaphores provide a lock that makes the waiting thread sleep, rather than spin, when contended.
Method
Description
spin_lock()
Acquires given lock
spin_lock_irq()
Disables local interrupts and acquires given lock
spin_lock_irqsave()
Saves current state of local interrupts, disables local interrupts, and acquires given lock
spin_unlock()
Releases given lock
spin_unlock_irq()
Releases given lock and enables local interrupts
spin_unlock_irqrestore()
Releases given lock and restores local interrupts to given previous state
spin_lock_init()
Dynamically initializes given spinlock_t
spin_trylock()
Tries to acquire given lock; if unavailable, returns nonzero
spin_is_locked()
Returns nonzero if the given lock is currently acquired, otherwise it returns zero
certain locking precautions must be taken when working with bottom halves. The function spin_lock_bh() obtains the given lock and disables all bottom halves. The function spin_unlock_bh() performs the inverse.
Because a bottom half may preempt process context code, if data is shared between a bottom half process context, you must protect the data in process context with both a lock and the disabling of bottom halves. Likewise, because an interrupt handler may preempt a bottom half, if data is shared between an interrupt handler and a bottom half, you must both obtain the appropriate lock and disable interrupts.
If a lock is used in an interrupt handler, you must also disable local interrupts (interrupt requests on the current processor) before obtaining the lock
So the pseudo code of spin lock
{
Disable preempt()
acquire_lock()
}
If used in ISR
{
Disable interrupts()
spin lock()
//critical region
spin_unlock()
}
OR
{
spinlock_t mr_lock = SPIN_LOCK_UNLOCKED;
unsigned long flags;
spin_lock_irqsave(&mr_lock, flags);
/* critical region ... */
spin_unlock_irqrestore(&mr_lock, flags);
}
The fact that a contended spin lock causes threads to spin (essentially wasting processor time) while waiting for the lock to become available is important. This behavior is the point of the spin lock. It is not wise to hold a spin lock for a long time. This is the nature of the spin lock: a lightweight single-holder lock that should be held for short durations. An alternative behavior when the lock is contended is to put the current thread to sleep and wake it up when it becomes available. Then the processor can go off and execute other code. This incurs a bit of overhead most notably the two context switches required to switch out of and back into the blocking thread, which is certainly a lot more code than the handful of lines used to implement a spin lock. Therefore, it is wise to hold spin locks for less than the duration of two context switches. Because most of us have better things to do than measure context switches, just try to hold the lock as little time as possible[1]. The semaphores provide a lock that makes the waiting thread sleep, rather than spin, when contended.
Method
Description
spin_lock()
Acquires given lock
spin_lock_irq()
Disables local interrupts and acquires given lock
spin_lock_irqsave()
Saves current state of local interrupts, disables local interrupts, and acquires given lock
spin_unlock()
Releases given lock
spin_unlock_irq()
Releases given lock and enables local interrupts
spin_unlock_irqrestore()
Releases given lock and restores local interrupts to given previous state
spin_lock_init()
Dynamically initializes given spinlock_t
spin_trylock()
Tries to acquire given lock; if unavailable, returns nonzero
spin_is_locked()
Returns nonzero if the given lock is currently acquired, otherwise it returns zero
certain locking precautions must be taken when working with bottom halves. The function spin_lock_bh() obtains the given lock and disables all bottom halves. The function spin_unlock_bh() performs the inverse.
Because a bottom half may preempt process context code, if data is shared between a bottom half process context, you must protect the data in process context with both a lock and the disabling of bottom halves. Likewise, because an interrupt handler may preempt a bottom half, if data is shared between an interrupt handler and a bottom half, you must both obtain the appropriate lock and disable interrupts.
Thursday, June 24, 2010
Kernel Directory Structure
Download: kernel.org
Browse: lxr.linux.no (with cross reference)
Directory structure
include: public headers
kernel: core kernel components (e.g., scheduler)
arch: hardware-dependent code
fs: file systems
mm: memory management
ipc: inter-process communication
drivers: device drivers
usr: user-space code
lib: common libraries
Browse: lxr.linux.no (with cross reference)
Directory structure
include: public headers
kernel: core kernel components (e.g., scheduler)
arch: hardware-dependent code
fs: file systems
mm: memory management
ipc: inter-process communication
drivers: device drivers
usr: user-space code
lib: common libraries
Monday, June 21, 2010
Adding a new system call
Assume we’d like add a system call calles “mycall” that takes two integers as input and return their sum.
1) Add “.long sys_mycall” at the end of the list in the file syscall_table.S.
---Full path for the file syscall_table.S is
usr/src/linux/arch/i386/kernel/syscall_table.S
NOTE: You can use the command sudo gedit syscall_table.S to edit the file
syscall_table.S. Beware that if you do not have the root privileges, system will not allow you to edit
any of the kernel files.
2) In file unistd.h
- Add #define __NR_mycall at the end of the list
(e.g. If the number of the last system call Last_System_Call_Num is 319 then the
line you shall add should be #define __NR_mycall 320.).
- Increment NR_syscalls by one (e.g. If before adding your system call total number of
system calls is 320, then this will be #define NR_syscalls 321.).
---Full path for the file unistd.h is /usr/src/linux/include/asm-i386/unistd.h
3) Add the following line at the end of the file syscalls.h:
asmlinkage long sys_mycall(int i, int j);
---Full path for the file syscalls.h is /usr/src/linux/include/linux/syscalls.h
4) Add mycall/ to core-y += in Makefile.
The line in the end shall look like:
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ mycall/
---Full path for Makefile is /usr/src/linux/Makefile.
5) Create a new directory in /usr/src/linux and name it mycall.
6) Create a new file called mycall.c in /usr/src/linux/mycall. Contents of the file shall be
as follows:
/*----------Start of mycall.c----------*/
#include <linux/linkage.h>
asmlinkage long sys_mycall(int i, int j) {
return(i+j);
}
/*-----------End of mycall.c-----------*/
*asmlinkage is used to look for the arguments on the kernel stack.
7) Create Makefile in /usr/src/linux/mycall. Makefile shall be like:
########## Start of Makefile ##########
obj-y := mycall.o
########## End of Makefile ##########
8) Create the following userspace program to test your system call and name it testmycall.c. The
contents of this file shall be:
/*---------- Start of testmycall.c File ----------*/
#include <unistd.h>
#include <stdio.h>
#define __NR_mycall
long mycall(int i, int j) {
return syscall(__NR_mycall, i, j);
};
int main() {
printf(“%d\n”, mycall(10, 20));
return 0;
}
/*---------- End of testmycall.c File ----------*/
9) Compile testmycall.c to test whether your system call works.
gcc testmycall.c –o testmycall
1) Add “.long sys_mycall” at the end of the list in the file syscall_table.S.
---Full path for the file syscall_table.S is
usr/src/linux/arch/i386/kernel/syscall_table.S
NOTE: You can use the command sudo gedit syscall_table.S to edit the file
syscall_table.S. Beware that if you do not have the root privileges, system will not allow you to edit
any of the kernel files.
2) In file unistd.h
- Add #define __NR_mycall
(e.g. If the number of the last system call Last_System_Call_Num is 319 then the
line you shall add should be #define __NR_mycall 320.).
- Increment NR_syscalls by one (e.g. If before adding your system call total number of
system calls is 320, then this will be #define NR_syscalls 321.).
---Full path for the file unistd.h is /usr/src/linux/include/asm-i386/unistd.h
3) Add the following line at the end of the file syscalls.h:
asmlinkage long sys_mycall(int i, int j);
---Full path for the file syscalls.h is /usr/src/linux/include/linux/syscalls.h
4) Add mycall/ to core-y += in Makefile.
The line in the end shall look like:
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ mycall/
---Full path for Makefile is /usr/src/linux/Makefile.
5) Create a new directory in /usr/src/linux and name it mycall.
6) Create a new file called mycall.c in /usr/src/linux/mycall. Contents of the file shall be
as follows:
/*----------Start of mycall.c----------*/
#include <linux/linkage.h>
asmlinkage long sys_mycall(int i, int j) {
return(i+j);
}
/*-----------End of mycall.c-----------*/
*asmlinkage is used to look for the arguments on the kernel stack.
7) Create Makefile in /usr/src/linux/mycall. Makefile shall be like:
########## Start of Makefile ##########
obj-y := mycall.o
########## End of Makefile ##########
8) Create the following userspace program to test your system call and name it testmycall.c. The
contents of this file shall be:
/*---------- Start of testmycall.c File ----------*/
#include <unistd.h>
#include <stdio.h>
#define __NR_mycall
long mycall(int i, int j) {
return syscall(__NR_mycall, i, j);
};
int main() {
printf(“%d\n”, mycall(10, 20));
return 0;
}
/*---------- End of testmycall.c File ----------*/
9) Compile testmycall.c to test whether your system call works.
gcc testmycall.c –o testmycall
Tuesday, May 25, 2010
System call Internals
Try this link
Sytem Call Internals
Linux Linkers and Loaders
http://www.linuxjournal.com/article/6463
Sytem Call Internals
Linux Linkers and Loaders
http://www.linuxjournal.com/article/6463
Creating a package using autoconf and automake
Please do refer this directly
http://mij.oltrelinux.com/devel/autoconf-automake/
In case this link does NOT turn up, use the following info
l.u. 21/11/2005
A first disclaimer is that I don't really like autoconf and automake. This is not the place for longer dissertations, so I won't spend more words on this. However, it is a matter of facts that many users just like to fetch your application, and issue the usual ./configure && make && make install right ahead.
So, this is a synthetic tutorial for moving a Makefile-based program to an autohell- (this is a popular way to refer to { autoconf, automake, libtool } that I will encourage) enabled package.
A somewhat complete, likely example is given here. If your PRE is not exactly like the one proposed, you just probably won't need to perform the corresponding following steps.
Definition of the problem:
PRE: you have a tree with
* sources in src/
* documentation in doc/
* man pages in man/
* some scripts in scripts/ (in general, stuff to be installed but not compiled)
* examples in examples/
POST: you want to
* check for the availability of the needed headers/libraries
* possibly adjust some things (say some path in scripts, or in docimentation) at compile-time
* install everything in its adequate place
So, this is what to do for moving with the very minimum effort:
1. Cleaning up
Move away every possible Makefile you have in the package (rename it for now)
2. Generating configure.ac
Run autoscan:
$ autoscan
autoscan tries to produce a suitable configure.ac file (autoconf's driver) by performing simple analyses on the files in the package. This is enough for the moment (many people are just happy with it as permanent). Autoscan actually produces a configure.scan file, so let it have the name autoconf will look for:
$ mv configure.scan configure.ac
-- note: configure.in was the name used for autoconf files, now deprecated.
3. Adjusting things
Adjust the few things left to you by autoscan: open configure.ac with your favourite editor
$ vim configure.ac
look in the very first lines for the following:
AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
and replace with your stuff, e.g.:
AC_INIT(pippo, 2.6, paperino@staff.pippo.org)
4. Generating a first configure script
At this point, you're ready to make autoconf produce the configure script:
$ autoconf
This produces two files: autom4te.cache and configure. The first one is a directory used for speeding up the job of autohell tools, and may be removed when releasing the package. The latter is the shell script called by final users.
In this status, what the configure script does is just checking for requirements as suggested by autoscan, so nothing very conclusive yet.
5. Generating suitable Makefiles
We have the system checking part. We now want the building and installing part. This is given by a cooperation of automake and autoconf. Automake generates some "templates" that autoconf-generated scripts will traduce into actual Makefile. A first, "main" automake file is needed in the root of the package:
$ vim Makefile.am
list the subdirectories where work is needed:
AUTOMAKE_OPTIONS = foreign
SUBDIRS = src doc examples man scripts
the first line sets the mode automake will behave like. "foreign" means not GNU, and is common for avoiding boring messages about files organized differently from what gnu expects.
The second line shows a list of subdirectories to descend for further work. The first one has stuff to compile, while the rest just needs installing, but we don't care in this file. We now prepare the Makefile.am file for each of these directories. Automake will step into each of them and produce the corresponding Makefile.in file. Those .in files will be used by autoconf scripts to produce the final Makefiles.
Edit src/Makefile.am:
$ vim src/Makefile.am
and insert:
# what flags you want to pass to the C compiler & linker
CFLAGS = --pedantic -Wall -std=c99 -O2
LDFLAGS =
# this lists the binaries to produce, the (non-PHONY, binary) targets in
# the previous manual Makefile
bin_PROGRAMS = targetbinary1 targetbinary2 [...] targetbinaryN
targetbinary1_SOURCES = targetbinary1.c myheader.h [...]
targetbinary2_SOURCES = targetbinary2.c
.
.
targetbinaryN_SOURCES = targetbinaryN.c
This was the most difficult one. In general, the uppercase, suffix part like "_PROGRAMS" is called primary and tells partially what to perform on the argument; the lowecase, prefix (it's not given a name) tells the directory where to install.
E.g.:
bin_PROGRAMS
installs binaries in $(PREFIX)/bin , and
sbin_PROGRAMS
installs in $(PREFIX)/sbin . More primaries will appear in the following, and here is a complete list of primaries. Not all can be prefixed to such primaries (see later for how to work around this problem).
Let us now move to mans:
$ vim man/Makefile.am
insert the following in it:
man_MANS = firstman.1 secondman.8 thirdman.3 [...]
yes, automake will deduce by itself what's needed for installing from this. Now edit for scripts:
$ vim scripts/Makefile.am
insert:
bin_SCRIPTS = script1.sh script2.sh [...]
The primary "SCRIPTS" instruct makefiles to just install the arguments, without compiling of course.
So far so good. Two jobs remain to define: installing examples and installing plain docs. This is the nasty part, as automake doesn't handle primaries for installing in the usual $(PREFIX)/share/doc/pippo . The workaround is to specify a further variable and using it as prefix:
$ vim doc/Makefile.am
docdir = $(datadir)/doc/@PACKAGE@
doc_DATA = README DONTS
if "abc" is wanted for prefix, "abcdir" is to be specified. E.g. the code above expands to /usr/local/share/doc/pippo ("@PACKAGE@" will be expanded by autoconf when producing the final Makefile, see below). $(datadir) is known by all configure scripts it generates. You may look for the list of directory variables.
Similarly for examples, but we want to install in $(PREFIX)/share/examples/pippo , so:
$ vim examples/Makefile.am
exampledir = $(datarootdir)/doc/@PACKAGE@
example_DATA = sample1.dat sample2.dat [...]
All these Makefile.am files now exist, but autoconf has now to be told about them.
6. Integrating the checking (autoconf) part and the building (automake) part
We insert now some macros in configure.ac for telling autoconf that the final Makefiles have to be produced after ./configure :
$ vim configure.ac
right after AC_INIT(), let initialize automake:
AM_INIT_AUTOMAKE(pippo, 2.6)
then, let autoconf generate a configure script that will output Makefiles for all of the above directories:
AC_OUTPUT(Makefile src/Makefile doc/Makefile examples/Makefile man/Makefile scripts/Makefile)
7. Making tools output the configure script and Makefile templates
we have now complete instructions for generating the famous configure script run by the users when installing, that both checks for building/running requirements and generates Makefiles for actually building and installing everything in place. Let now actually make tools generate such script:
$ aclocal
This generates a file aclocal.m4 that contains macros for automake things, e.g. AM_INIT_AUTOMAKE.
$ automake --add-missing
Automake now reads configure.ac and the top-level Makefile.am, interprets them (e.g. see further work has to be done in some subdirectories) and, for each Makefile.am produces a Makefile.in. The argument --add-missing tells automake to provide default scripts for reporting errors, installing etc, so it can be omitted in the next runs.
Finally, let autoconf build the configure script:
$ autoconf
This produces the final, full-featured configure shell script.
8. Further customizations
if you need to perform custom checks, or actions in configure, just write the (shell) code somewhere in configure.ac (before OUTPUT commands), then run autoconf again. For some checks, autoconf may already provide some macro: look in the list of autoconf macros before writing useless code.
How do things work from now on
The user first runs:
$ ./configure
The shell script just generated will:
1. scan for dependencies on the basis of the AC_* macros instructed in configure.ac. If there's something wrong/missing in the system, an opportune error message will be dumped.
2. for each Makefile requested in AC_OUTPUT(), translate the Makefile.in template for generating the final Makefile. The main makefile will provide the most common targets like install, clean, distclean, uninstall et al.
if configure succeeds, all the Makefile files are available. The user then issues:
$ make
The target all from the main Makefile will be worked. This target expands into all the hidden targets to first build what you requested. Then, by mean of
# make install
everything is installed.
http://mij.oltrelinux.com/devel/autoconf-automake/
In case this link does NOT turn up, use the following info
A tutorial for porting to autoconf & automake
l.u. 21/11/2005
A first disclaimer is that I don't really like autoconf and automake. This is not the place for longer dissertations, so I won't spend more words on this. However, it is a matter of facts that many users just like to fetch your application, and issue the usual ./configure && make && make install right ahead.
So, this is a synthetic tutorial for moving a Makefile-based program to an autohell- (this is a popular way to refer to { autoconf, automake, libtool } that I will encourage) enabled package.
A somewhat complete, likely example is given here. If your PRE is not exactly like the one proposed, you just probably won't need to perform the corresponding following steps.
Definition of the problem:
PRE: you have a tree with
* sources in src/
* documentation in doc/
* man pages in man/
* some scripts in scripts/ (in general, stuff to be installed but not compiled)
* examples in examples/
POST: you want to
* check for the availability of the needed headers/libraries
* possibly adjust some things (say some path in scripts, or in docimentation) at compile-time
* install everything in its adequate place
So, this is what to do for moving with the very minimum effort:
1. Cleaning up
Move away every possible Makefile you have in the package (rename it for now)
2. Generating configure.ac
Run autoscan:
$ autoscan
autoscan tries to produce a suitable configure.ac file (autoconf's driver) by performing simple analyses on the files in the package. This is enough for the moment (many people are just happy with it as permanent). Autoscan actually produces a configure.scan file, so let it have the name autoconf will look for:
$ mv configure.scan configure.ac
-- note: configure.in was the name used for autoconf files, now deprecated.
3. Adjusting things
Adjust the few things left to you by autoscan: open configure.ac with your favourite editor
$ vim configure.ac
look in the very first lines for the following:
AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
and replace with your stuff, e.g.:
AC_INIT(pippo, 2.6, paperino@staff.pippo.org)
4. Generating a first configure script
At this point, you're ready to make autoconf produce the configure script:
$ autoconf
This produces two files: autom4te.cache and configure. The first one is a directory used for speeding up the job of autohell tools, and may be removed when releasing the package. The latter is the shell script called by final users.
In this status, what the configure script does is just checking for requirements as suggested by autoscan, so nothing very conclusive yet.
5. Generating suitable Makefiles
We have the system checking part. We now want the building and installing part. This is given by a cooperation of automake and autoconf. Automake generates some "templates" that autoconf-generated scripts will traduce into actual Makefile. A first, "main" automake file is needed in the root of the package:
$ vim Makefile.am
list the subdirectories where work is needed:
AUTOMAKE_OPTIONS = foreign
SUBDIRS = src doc examples man scripts
the first line sets the mode automake will behave like. "foreign" means not GNU, and is common for avoiding boring messages about files organized differently from what gnu expects.
The second line shows a list of subdirectories to descend for further work. The first one has stuff to compile, while the rest just needs installing, but we don't care in this file. We now prepare the Makefile.am file for each of these directories. Automake will step into each of them and produce the corresponding Makefile.in file. Those .in files will be used by autoconf scripts to produce the final Makefiles.
Edit src/Makefile.am:
$ vim src/Makefile.am
and insert:
# what flags you want to pass to the C compiler & linker
CFLAGS = --pedantic -Wall -std=c99 -O2
LDFLAGS =
# this lists the binaries to produce, the (non-PHONY, binary) targets in
# the previous manual Makefile
bin_PROGRAMS = targetbinary1 targetbinary2 [...] targetbinaryN
targetbinary1_SOURCES = targetbinary1.c myheader.h [...]
targetbinary2_SOURCES = targetbinary2.c
.
.
targetbinaryN_SOURCES = targetbinaryN.c
This was the most difficult one. In general, the uppercase, suffix part like "_PROGRAMS" is called primary and tells partially what to perform on the argument; the lowecase, prefix (it's not given a name) tells the directory where to install.
E.g.:
bin_PROGRAMS
installs binaries in $(PREFIX)/bin , and
sbin_PROGRAMS
installs in $(PREFIX)/sbin . More primaries will appear in the following, and here is a complete list of primaries. Not all can be prefixed to such primaries (see later for how to work around this problem).
Let us now move to mans:
$ vim man/Makefile.am
insert the following in it:
man_MANS = firstman.1 secondman.8 thirdman.3 [...]
yes, automake will deduce by itself what's needed for installing from this. Now edit for scripts:
$ vim scripts/Makefile.am
insert:
bin_SCRIPTS = script1.sh script2.sh [...]
The primary "SCRIPTS" instruct makefiles to just install the arguments, without compiling of course.
So far so good. Two jobs remain to define: installing examples and installing plain docs. This is the nasty part, as automake doesn't handle primaries for installing in the usual $(PREFIX)/share/doc/pippo . The workaround is to specify a further variable and using it as prefix:
$ vim doc/Makefile.am
docdir = $(datadir)/doc/@PACKAGE@
doc_DATA = README DONTS
if "abc" is wanted for prefix, "abcdir" is to be specified. E.g. the code above expands to /usr/local/share/doc/pippo ("@PACKAGE@" will be expanded by autoconf when producing the final Makefile, see below). $(datadir) is known by all configure scripts it generates. You may look for the list of directory variables.
Similarly for examples, but we want to install in $(PREFIX)/share/examples/pippo , so:
$ vim examples/Makefile.am
exampledir = $(datarootdir)/doc/@PACKAGE@
example_DATA = sample1.dat sample2.dat [...]
All these Makefile.am files now exist, but autoconf has now to be told about them.
6. Integrating the checking (autoconf) part and the building (automake) part
We insert now some macros in configure.ac for telling autoconf that the final Makefiles have to be produced after ./configure :
$ vim configure.ac
right after AC_INIT(), let initialize automake:
AM_INIT_AUTOMAKE(pippo, 2.6)
then, let autoconf generate a configure script that will output Makefiles for all of the above directories:
AC_OUTPUT(Makefile src/Makefile doc/Makefile examples/Makefile man/Makefile scripts/Makefile)
7. Making tools output the configure script and Makefile templates
we have now complete instructions for generating the famous configure script run by the users when installing, that both checks for building/running requirements and generates Makefiles for actually building and installing everything in place. Let now actually make tools generate such script:
$ aclocal
This generates a file aclocal.m4 that contains macros for automake things, e.g. AM_INIT_AUTOMAKE.
$ automake --add-missing
Automake now reads configure.ac and the top-level Makefile.am, interprets them (e.g. see further work has to be done in some subdirectories) and, for each Makefile.am produces a Makefile.in. The argument --add-missing tells automake to provide default scripts for reporting errors, installing etc, so it can be omitted in the next runs.
Finally, let autoconf build the configure script:
$ autoconf
This produces the final, full-featured configure shell script.
8. Further customizations
if you need to perform custom checks, or actions in configure, just write the (shell) code somewhere in configure.ac (before OUTPUT commands), then run autoconf again. For some checks, autoconf may already provide some macro: look in the list of autoconf macros before writing useless code.
How do things work from now on
The user first runs:
$ ./configure
The shell script just generated will:
1. scan for dependencies on the basis of the AC_* macros instructed in configure.ac. If there's something wrong/missing in the system, an opportune error message will be dumped.
2. for each Makefile requested in AC_OUTPUT(), translate the Makefile.in template for generating the final Makefile. The main makefile will provide the most common targets like install, clean, distclean, uninstall et al.
if configure succeeds, all the Makefile files are available. The user then issues:
$ make
The target all from the main Makefile will be worked. This target expands into all the hidden targets to first build what you requested. Then, by mean of
# make install
everything is installed.
Monday, May 24, 2010
What is PORTABLE and UN-PORTABLE CODE
Unportable Code:
implementation-defined— The compiler-writer chooses what happens, and has to document it.
Example: whether the sign bit is propagated, when shifting an int right.
unspecified— The behavior for something correct, on which the standard does not impose any requirements.
Example: the order of argument evaluation.
Bad Code:
undefined— The behavior for something incorrect, on which the standard does not impose any requirements. Anything is allowed to happen, from nothing, to a warning message to program termination, to CPU meltdown, to launching nuclear missiles (assuming you have the correct hardware option installed).
Example: what happens when a signed integer overflows.
a constraint— This is a restriction or requirement that must be obeyed. If you don't, your program behavior becomes undefined in the sense above. Now here's an amazing thing: it's easy to tell if something is a constraint or not, because each topic in the standard has a subparagraph labelled "Constraints" that lists them all. Now here's an even more amazing thing: the standard specifies [5] that compilers only have to produce error messages for violations of syntax and constraints! This means that any semantic rule that's not in a constraints subsection can be broken, and since the behavior is undefined, the compiler is free to do anything and doesn't even have to warn you about it!
Example: the operands of the % operator must have integral type. So using a non-integral type with % must cause a diagnostic.
Example of a rule that is not a constraint: all identifiers declared in the C standard header files are reserved for the implementation, so you may not declare a function called malloc() because a standard header file already has a function of that name. But since this is not a constraint, the rule can be broken, and the compiler doesn't have to warn you
Portable Code:
strictly-conforming— A strictly-conforming program is one that:
• only uses specified features.
• doesn't exceed any implementation-defined limit.
• has no output that depends on implementation-defined, unspecified, or undefined features.
This was intended to describe maximally portable programs, which will always produce the identical output whatever they are run on. In fact, it is not a very interesting class because it is so small compared to the universe of conforming programs. For example, the following program is not strictly conforming:
#include
#include
int main() { (void) printf("biggest int is %d", INT_MAX);
return 0;}
/* not strictly conforming: implementation-defined output! */
conforming— A conforming program can depend on the nonportable features of an implementation. So a program is conforming with respect to a specific implementation, and the same program may be nonconforming using a different compiler. It can have extensions, but not extensions that alter the
behavior of a strictly-conforming program. This rule is not a constraint, however, so don't expect the compiler to warn you about violations that render your program nonconforming!
The program example above is conforming.
implementation-defined— The compiler-writer chooses what happens, and has to document it.
Example: whether the sign bit is propagated, when shifting an int right.
unspecified— The behavior for something correct, on which the standard does not impose any requirements.
Example: the order of argument evaluation.
Bad Code:
undefined— The behavior for something incorrect, on which the standard does not impose any requirements. Anything is allowed to happen, from nothing, to a warning message to program termination, to CPU meltdown, to launching nuclear missiles (assuming you have the correct hardware option installed).
Example: what happens when a signed integer overflows.
a constraint— This is a restriction or requirement that must be obeyed. If you don't, your program behavior becomes undefined in the sense above. Now here's an amazing thing: it's easy to tell if something is a constraint or not, because each topic in the standard has a subparagraph labelled "Constraints" that lists them all. Now here's an even more amazing thing: the standard specifies [5] that compilers only have to produce error messages for violations of syntax and constraints! This means that any semantic rule that's not in a constraints subsection can be broken, and since the behavior is undefined, the compiler is free to do anything and doesn't even have to warn you about it!
Example: the operands of the % operator must have integral type. So using a non-integral type with % must cause a diagnostic.
Example of a rule that is not a constraint: all identifiers declared in the C standard header files are reserved for the implementation, so you may not declare a function called malloc() because a standard header file already has a function of that name. But since this is not a constraint, the rule can be broken, and the compiler doesn't have to warn you
Portable Code:
strictly-conforming— A strictly-conforming program is one that:
• only uses specified features.
• doesn't exceed any implementation-defined limit.
• has no output that depends on implementation-defined, unspecified, or undefined features.
This was intended to describe maximally portable programs, which will always produce the identical output whatever they are run on. In fact, it is not a very interesting class because it is so small compared to the universe of conforming programs. For example, the following program is not strictly conforming:
#include
#include
int main() { (void) printf("biggest int is %d", INT_MAX);
return 0;}
/* not strictly conforming: implementation-defined output! */
conforming— A conforming program can depend on the nonportable features of an implementation. So a program is conforming with respect to a specific implementation, and the same program may be nonconforming using a different compiler. It can have extensions, but not extensions that alter the
behavior of a strictly-conforming program. This rule is not a constraint, however, so don't expect the compiler to warn you about violations that render your program nonconforming!
The program example above is conforming.
Subscribe to:
Posts (Atom)