I read the tutorial which advises me to run at util-linux package
./configure
I get
configuring util-linux-2.12q
You don't have <scsi/scsi.h>
You don't have <linux/blkpg.h>
You don't have <linux/kd.h>
You have <locale.h>You have <langinfo.h>
You have <sys/user.h>
You have <uuid/uuid.h>
You have <rpcsvc/nfs_prot.h>
You don't have <asm/types.h>
You don't have <linux/raw.h>
You have <stdint.h>
You don't have <sys/io.h>
You have inet_aton()
You have fsync()
You have getdomainname()
You have nanosleep()
You don't have personality()
You don't have updwtmp()
You have fseeko()
You have lchown()
You don't have rpmatch()
You have <term.h>
You have ncurses. Using <ncurses.h>.
You have termcap
You don't need -lcrypt
Strange... Static compilation fails here.
You don't have native language support
You have __progname
You don't have <pty.h> and openpty()
You have wide character support
You don't have SYS_pivot_root
You have a tm_gmtoff field in struct tm
Your rpcgen output does not compile - using pregenerated code
You have zlib
You don't have blkid
It then advises me to run the following command at misc-utils
make rename
I get the following warning
cc -pipe -O2 -mtune=i386 -fomit-frame-pointer -I../lib -Wall -Wmissing-prototypes -Wstrict-prototypes -DNCH=1 -D_FILE_OFFSET_BITS=64 -DSBINDIR=\"/sbin\" -DUSRSBINDIR=\"/usr/sbin\" -DLOGDIR=\"/var/log\" -DVARPATH=\"/var\" -DLOCALEDIR=\"/usr/share/locale\" -O2 -s rename.c -o rename
ld warning: option -s is obsolete and being ignored
How can you install rename -command for Mac?
That's a warning, not an error.
I've just tried this myself and it has built a rename executable.
Easily install rename using Homebrew
brew install rename
Do compile rename from linux. There are some minor differences to the indications in the tutorial. I used version 2.22 from the file util-linux-2.22.tar.gz
Download it and uncompress it. Go to the uncompressed folder in a terminal.
Don't just run ./configure, use this command with flags instead:
./configure --disable-su --disable-sulogin --disable-login
then from that very same folder, NOT changing into misc-utils, you do make rename
That's all, in the current folder you'll have the executable and in the misc-utils the man documentation if you need it.
Can you not just use mv instead of trying to compile rename? Maybe even alias it to rename?
(EDIT: Ignore my comment about build-essentials - as pointed out by yangyang, it looks like it should have built ok anyhow)
Try this:
function rename { from=$1; to=$2; shift 2; for i in "$#"; do j=`echo $i | sed "s/$from/$to/"`; mv "$i" "$j"; done }
Paste it into your .profile or .bashrc and run it just like the Red Hat rename utility:
$rename foo bar *.txt
Turns foo1.txt, foo2.txt and foofoo.txt into bar1.txt, bar2.txt but, somewhat irritatingly, barfoo.txt. Maybe someone can tweak it to fix this.
Test it by putting 'echo' before 'mv' so that it outputs a list of all changes it will make without making them.
Related
I am new to linux programming and learning it from The Linux Programming Interface by Michael Kerrisk.
I have to compile my first program that has dependencies.
Directory structure:
--linux-programs
|--seek_io.c
|--lib
|--tlpi_hdr.h
|--error_functions.h
|--error_functions.c
|--get_num.h
|--ename.c.inc
I want to compile seek_io.c program with dependencies in the lib directory, so that I can see how the program works.
I tried a few things, absolutely clueless on how they work following this stackoverflow answer. I get all sorts of errors as I am an absolute beginner to Linux programming, not to programming, linux OS and C.
Trials:
gcc -I ./lib/ -c ./lib/error_functions.c and then gcc -o seek_io.c ./error_function.o gives error:
/usr/lib/gcc/x86_64-linux-gnu/crt1.o: In function _start:
(.text+0x20): undefined reference to main
collect2: error: ld returned 1 exit status
After this run, on ls I find that my seek_io.c is not listed.
Basically the author of the book says for tlpi_hdr.h file:
This header file includes various other header files used by many of the example programs, defines a Boolean data type, and defines macros for calculating the minimum and maximum of two numeric values. Using this header file allows us to make the example programs a bit shorter.
Link to codes for files mentioned above:
tlpi_hdr.h
error_functions.h
error_functions.c
get_num.h
get_num.c
seek_io.c
The problem is with your second gcc command, where you're using the -o file to specify the output file where to store the resulting executable file, but passing it the name of the C source file seek_io.c instead...
gcc -o seek_io.c ./error_function.o
This means link file error_function.o and store the executable in seek_io.c. This fails because there is no main function, which is needed for a standalone executable, so your C source file is not overwritten by the failing link command.
You can fix this easily by passing the -o option a proper output file name, which in the case (of this link command) should be the name of the executable that you want to create, such as seek_io:
gcc -o seek_io seek_io.c ./error_function.o
(But this will fail without a -I ./lib/, since seek_io.c includes tlpi_hdr.h which is in that directory. If you add it to that command, it should work.)
You can also decide to split the compile and link steps in two separate steps (the command above will both compile seek_io.c into an object file and then link the two object files into an executable) with:
$ gcc -I ./lib/ -c ./lib/error_functions.c
$ gcc -I ./lib/ -c seek_io.c
$ gcc -o seek_io seek_io.o error_function.o
One final nitpick is that for the -I flag to specify the directories where to search for the include files, the more common usage has no space between the flag itself and the directory name, so you'll most commonly see -I./lib or even -Ilib.
$ gcc -Ilib -c ./lib/error_functions.c
$ gcc -Ilib -c seek_io.c
$ gcc -o seek_io seek_io.o error_function.o
I am wondering why gcc/g++ doesn't have an option to place the generated object files into a specified directory.
For example:
mkdir builddir
mkdir builddir/objdir
cd srcdir
gcc -c file1.c file2.c file3.c **--outdir=**../builddir/objdir
I know that it's possible to achive this with separate -o options given to the compiler, e.g.:
gcc -c file1.c -o ../builddir/objdir/file1.o
gcc -c file2.c -o ../builddir/objdir/file2.o
gcc -c file3.c -o ../builddir/objdir/file3.o
... and I know that I can write Makefiles via VPATH and vpath directives to simplify this.
But that's a lot of work in a complex build environment.
I could also use
gcc -c file1.c file2.c file3.c
But when I use this approach my srcdir is full of .o garbage afterwards.
So I think that an option with the semantics of --outdir would be very useful.
What is your opinion?
EDIT: our Makefiles are written in such a way that .o files actually placed into builddir/obj. But I am simply wondering if there might be a better approach.
EDIT: There are several approaches which place the burden to achieve the desired behavior to the build system (aka Make, CMake etc.). But I consider them all as being workarounds for a weakness of gcc (and other compilers too).
This is the chopped down makefile for one of my projects, which compiles the sources in 'src' and places the .o files in the directory "obj". The key bit is the the use of the patsubst() function - see the GNU make manual (which is actually a pretty good read) for details:
OUT = lib/alib.a
CC = g++
ODIR = obj
SDIR = src
INC = -Iinc
_OBJS = a_chsrc.o a_csv.o a_enc.o a_env.o a_except.o \
a_date.o a_range.o a_opsys.o
OBJS = $(patsubst %,$(ODIR)/%,$(_OBJS))
$(ODIR)/%.o: $(SDIR)/%.cpp
$(CC) -c $(INC) -o $# $< $(CFLAGS)
$(OUT): $(OBJS)
ar rvs $(OUT) $^
.PHONY: clean
clean:
rm -f $(ODIR)/*.o $(OUT)
How about changing to the directory and running the compile from there:
cd builddir/objdir
gcc ../../srcdir/file1.c ../../srcdir/file2.c ../../srcdir/file3.c
That's it. gcc will interpret includes of the form #include "path/to/header.h" as starting in the directory the file exists so you don't need to modify anything.
A trivial but effective workaround is to add the following right after the gcc call in your Makefile:
mv *.o ../builddir/objdir
or even a soft-clean (possibly recursive) after the compilation is done, like
rm -f *.o
or
find . -name \*.o -exec rm {} \;
You can use a simple wrapper around gcc that will generate the necessary -o options and call gcc:
$ ./gcc-wrap -c file1.c file2.c file3.c --outdir=obj
gcc -o obj/file1.o -c file1.c
gcc -o obj/file2.o -c file2.c
gcc -o obj/file3.o -c file3.c
Here is such a gcc_wrap script in its simplest form:
#!/usr/bin/perl -w
use File::Spec;
use File::Basename;
use Getopt::Long;
Getopt::Long::Configure(pass_through);
my $GCC = "gcc";
my $outdir = ".";
GetOptions("outdir=s" => \$outdir)
or die("Options error");
my #c_files;
while(-f $ARGV[-1]){
push #c_files, pop #ARGV;
}
die("No input files") if(scalar #c_files == 0);
foreach my $c_file (reverse #c_files){
my($filename, $c_path, $suffix) = fileparse($c_file, ".c");
my $o_file = File::Spec->catfile($outdir, "$filename.o");
my $cmd = "$GCC -o $o_file #ARGV $c_file";
print STDERR "$cmd\n";
system($cmd) == 0 or die("Could not execute $cmd: $!");
}
Of course, the standard way is to solve the problem with Makefiles, or simpler, with CMake or bakefile, but you specifically asked for a solution that adds the functionality to gcc, and I think the only way is to write such a wrapper. Of course, you could also patch the gcc sources to include the new option, but that might be hard.
I believe you got the concept backwards...?!
The idea behind Makefiles is that they only process the files that have been updated since the last build, to cut down on (re-)compilation times. If you bunch multiple files together in one compiler run, you basically defeat that purpose.
Your example:
gcc -c file1.c file2.c file3.c **--outdir=**../builddir/objdir
You didn't give the 'make' rule that goes with this command line; but if any of the three files has been updated, you have to run this line, and recompile all three files, which might not be necessary at all. It also keeps 'make' from spawning a seperate compilation process for each source file, as it would do for seperate compilation (when using the '-j' option, as I would strongly suggest).
I wrote a Makefile tutorial elsewhere, which goes into some extra detail (such as auto-detecting your source files instead of having them hard-coded in the Makefile, auto-determining include dependencies, and inline testing).
All you would have to do to get your seperate object directory would be to add the appropriate directory information to the OBJFILES := line and the %.o: %.c Makefile rule from that tutorial. Neil Butterworth's answer has a nice example of how to add the directory information.
(If you want to use DEPFILES or TESTFILES as described in the tutorial, you'd have to adapt the DEPFILES := and TSTFILES := lines plus the %.t: %.c Makefile pdclib.a
rule, too.)
Meanwhile I found a "half-way" solution by using the -combine option.
Example:
mkdir builddir
mkdir builddir/objdir
cd srcdir
gcc -combine -c file1.c file2.c file3.c -o ../builddir/objdir/all-in-one.o
this "combines" all source files into one single object file.
However, this is still "half-way" because it needs to recompile everything when only one source file changes.
I think that telling pass gcc doesn't have an separate option to say where to put object file, since it already has it. It's "-c" - it says in what directory to put object.
Having additional flag for directory only must change meening of "-c".
For example:
gcc -c file.c -o /a/b/c/file.o --put-object-in-dir-non-existing-option /a1/a2/a3
You can not put /a/b/c/file.o under /a1/a2/a3, since both paths are absolute. Thus "-c" should be changed to name object file only.
I advise you to consider a replacement of makefile, like cmake, scons and other.
This will enable to implement build system as for for simple project as well as for bigger one too.
See for example how it's easy to compile using cmake your example.
Just create file CMakeList.txt in srcdir/:
cmake_minimum_required(VERSION 2.6)
project(test)
add_library(test file1.c file2c file3.c)
And now type:
mkdir -p builddir/objdir
cd builddir/objdir
cmake ../../srcdir
make
That's all, object files will reside somewhere under builddir/objdir.
I personaly use cmake and find it very convinient. It automatically generates dependencies and has other goodies.
I am trying to figure out the same thing. For me this worked
CC = g++
CFLAGS = -g -Wall -Iinclude
CV4LIBS = `pkg-config --libs opencv4`
CV4FLAGS = `pkg-config --cflags opencv4`
default: track
track: main.o
$(CC) -o track $(CV4LIBS) ./obj/main.o
ALLFLAGS = $(CFLAGS) $(CV4FLAGS)
main.o: ./src/main.cpp ./include/main.hpp
$(CC) $(ALLFLAGS) -c ./src/main.cpp $(CV4LIBS) -o ./obj/main.o
``
This is among the problems autoconf solves.
If you've ever done ./configure && make you know what autoconf is: it's the tool that generates those nice configure scripts. What not everyone knows is that you can instead do mkdir mybuild && cd mybuild && ../configure && make and that will magically work, because autoconf is awesome that way.
The configure script generates Makefiles in the build directory. Then the entire build process happens there. So all the build files naturally appear there, not in the source tree.
If you have source files doing #include "../banana/peel.h" and you can't change them, then it's a pain to make this work right (you have to copy or symlink all the header files into the build directory). If you can change the source files to say #include "libfood/comedy/banana/peel.h" instead, then you're all set.
autoconf is not exactly easy, especially for a large existing project. But it has its advantages.
Personally for single files I do this,
rm -rf temps; mkdir temps; cd temps/ ; gcc -Wall -v --save-temps ../thisfile.c ; cd ../ ; geany thisfile.c temps/thisfile.s temps/thisfile.i
temps folder will keep all the object, preprocessed and assembly files.
This is a crude way of doing things and I would prefer above answers using Makefiles.
I am facing issues with a make command. I am compiling Scilab on RHEL for ppc64. The ./configure went well, now when I did make all, I have an issue when compiling the module umfpack. I can reproduce this error by entering the modules/umfpack folder, and by typing there make all. This is the output:
enter[root#rhel70-misurio umfpack]# /bin/sh ../../libtool --tag=CC --mode=link gcc -D_LARGEFILE64_SOURCE -DNDEBUG -fno-stack-protector -g -O2 -version-number 5:5:1 -Wl,--no-as-needed -o libsciumfpack.la -rpath /usr/local/lib/scilab sci_gateway/c/libsciumfpack_la-gw_umfpack.lo sci_gateway/c/libsciumfpack_la-sci_res_with_prec.lo sci_gateway/c/libsciumfpack_la-sci_taucs_chdel.lo sci_gateway/c/libsciumfpack_la-sci_taucs_chfact.lo sci_gateway/c/libsciumfpack_la-sci_taucs_chget.lo sci_gateway/c/libsciumfpack_la-sci_taucs_chinfo.lo sci_gateway/c/libsciumfpack_la-sci_taucs_chsolve.lo sci_gateway/c/libsciumfpack_la-sci_umf_ludel.lo sci_gateway/c/libsciumfpack_la-sci_umf_lufact.lo sci_gateway/c/libsciumfpack_la-sci_umf_luget.lo sci_gateway/c/libsciumfpack_la-sci_umf_luinfo.lo sci_gateway/c/libsciumfpack_la-sci_umf_lusolve.lo sci_gateway/c/libsciumfpack_la-sci_umfpack.lo libsciumfpack-algo.la -L-lumfpack -lsuitesparseconfig -lumfpack -lpthread -ldl -lcurses -lm
../../libtool: line 6000: cd: -l: invalid option
cd: usage: cd [-L|[-P [-e]]] [dir]
libtool: link: cannot determine absolute directory name of `-lumfpack'
So it is apparent that somewhere the code is doing "cd -"something. But where...? this is folder where I am.
[root#rhel70-hostname umfpack]# ls
etc libsciumfpack-algo.la make_all_log sci_gateway umfpack.iss
examples license.txt Makefile src UMFPACK_license.txt
help locales Makefile.am TAUCS_license.txt
includes macros Makefile.in tests
Which are the candidates, in your opinion, where I have to investigate where the mistake is? What would you do in my place to debug?
Thanks!
Many thanks for your suggestions! I went into the libtool file and indeed I found that at line 6'000 there was this line of code:
absdir=`cd "$dir" && pwd`
test -z "$absdir" && \
func_fatal_error "cannot determine absolute directory name of \`$dir'"
And I realised that it was doing "cd -lumfpack" in the script. That was an input I had given to the ./configure script, in which I had to explicitly provide the libumfpack and libsuitesparseparseconfig as an option, since it was using other libraries by default. In that option, I had given:
--with-umfpack-library="-lumfpack -lsuitesparseconfig"
so then make was doing "cd -lumfpack". So I thought about providing the absolute path of both libraries! So I gave as input:
--with-umfpack-library="/usr/local/lib/libumfpack.a /usr/local/lib/libsuitesparseconfig.a"
And it successfully ran the configure script and the make.
Another "solution" would have been to remove the umfpack libraries altogether with the option to the configure script:
--without-umfpack
Hope it helps future programmers compiling Scilab!
Honestly, I think another way could have been feasible, that is specifiying the libumfpack and libsuitesparseconfig libraries in the configure script directly, but I didn't have time then to investigate this. If I will do, I will update this post.
I compile this program:
#include <stdio.h>
int main()
{
printf("Hello World!");
return 0;
}
With this command:
gcc -c "hello.c" -o hello
And when I try to execute hello, I get
bash: ./hello: Permission denied
Because the permissions are
-rw-r--r-- 1 nathan nathan 856 2010-09-17 23:49 hello
For some reason??
But whatever... after changing the permissions and trying to execute again, I get
bash: ./hello: cannot execute binary file
I'm using gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3
What am I doing wrong here? It's gotta be obvious... it's just too late for me to keep using my tired eyes to try and figure out this simple problem....
P.S. I do (sometimes) work on programs more sophisticated than Hello World, but gcc is doing this across the board...
Take the -c out. That's for making object files, not executables.
The -c flag tells it not to link, so you have an object file, not a binary executable.
In fact, if you ran this without the -o flag, you would find that the default output file would be hello.o.
For reference (and giggles), the man entry on the -c flag:
-c Compile or assemble the source files, but do not link. The linking stage simply is not done.
The ultimate output is in the form of an object file for each source file.
By default, the object file name for a source file is made by replacing the suffix .c, .i, .s,
etc., with .o.
Unrecognized input files, not requiring compilation or assembly, are ignored.
Compile with: gcc hello.c -o hello
I'm having difficulty with the linker when it comes to compiling a sample program that uses the POSIX aio library (e.g. aio_read(), aio_write(), etc) on Linux.
I'm running Ubuntu with a 2.6 kernel, and have used the apt-get utility to install libaio. But even though I'm linking with the aio library, the compiler still gives me linker errors.
root#ubuntu:/home# g++ -L /usr/lib/libaio.a aio.cc -oaio
/tmp/cc5OE58r.o: In function `main':
aio.cc:(.text+0x156): undefined reference to `aio_read'
aio.cc:(.text+0x17b): undefined reference to `aio_error'
aio.cc:(.text+0x191): undefined reference to `aio_return'
collect2: ld returned 1 exit status
Where are all these aio_x functions actually defined, if not in the library libaio.a?
I also had issues linking against libaio in spite of the aio package being correctly installed and the -lrt flag being present.
It turned out that placing -l flags later (for example, last) in the gcc command invocation sometimes fixes this issue. I stumbled upon this solution here on Stack Overflow.
I stopped doing this:
gcc -Wall -Werror -g -o myExe -lrt myExe.c
And started doing this:
gcc -Wall -Werror -g -o myExe myExe.c -lrt
EDIT: according the the man page, libaio.so is not the correct library to link to:
man aio_read
SYNOPSIS
#include <aio.h>
int aio_read(struct aiocb *aiocbp);
Link with -lrt.
so you should link with this:
g++ -lrt aio.cc -o aio
The way libraries work with gcc is like this:
-L adds directory dir to the list of directories to be searched for -l.
-l adds a library itself, if the file is named libsomename.so, you just use "-lsomename"
Does -L specify the search path and -l specifies the actual library?
You want -laio in order to link to libaio. The argument of -o is what you want the compiled executable to be called.
Try:
sudo apt-get install libaio-dev
Then make sure you specify -laio on the link line.
Okay, Evan Teran is correct - it worked when I linked with -lrt. It seems the aio_x functions are defined in a general POSIX extension library.
Thanks, Evan.