Long story short: I worked on relative rpath linking with this script (that uses automake, autoconf, libtool).
The problem is that the final rpath/runpath entry in the binary executable or so file still has the absolute path:
it turned out libtool is configured by default like this with hardcode_libdir_flag_spec to include any -L value if it's set in LDFLAGS
The only question remains: how and at which point (what's the proper way) can I set other libtool variables, like hardcode_minus_L. (I've searched for it on the net, but I couldn't find anything.)
I tried to do the following:
after configure is called I tried to replace the value of the variable with sed in libtool file (in the proper directory): it worked but when make is called it overwrote the whole libtool file again (it was regenerated)
Note, that 2 binary files are effected by this, entry for rpath/runpath with objdump -p:
libcurl.so : RUNPATH /home/user1/lib/rtorrent-0.9.7-1.5.3/lib:$ORIGIN/../lib
rtorrent : RUNPATH $ORIGIN/../lib:/home/user1/lib/rtorrent-0.9.7-1.5.3/lib
Thanks
I don't know if modifying the generated libtool script is the best approach to solve your problem. But if you go this way, you need to make the approach robust by executing your sed command within AC_CONFIG_COMMANDS.
The libtool script is generated during config.status as an configuration command (AC_CONFIG_COMMANDS: https://www.gnu.org/software/autoconf/manual/autoconf.html#Configuration-Commands) .
config.status: executing libtool commands
You can modify this generated file by adding another AC_CONFIG_COMMANDS.
We use following to alter the prefer_static_libs variable:
AC_CONFIG_COMMANDS([libtool-fix-linker-preference],
[${SED} -e '1,/prefer_static_libs=/ s/prefer_static_libs=.*$/prefer_static_libs=yes/' \
libtool > libtool.fix && mv libtool.fix libtool])
You need to trigger your AC_CONFIG_COMMANDS after LT_INIT.
configure/config.status reports the execution:
config.status: executing libtool commands
config.status: executing libtool-fix-linker-preference commands
Hope that helps,
Christian
It turned out it's fairly easy to modify these variables in configure.ac, no need for sed - after fiddling around and taking a look into the generated scripts. The only thing can be confusing that these variables can be applied to
tags defined in the given project.
E.g. to change hardcode_libdir_flag_spec to an empty value in rtorrent project (means it will break compilation), you would insert into configure.ac:
_LT_TAGVAR(hardcode_libdir_flag_spec, )=""
_LT_TAGVAR(hardcode_libdir_flag_spec, CXX)=""
_LT_TAGVAR(hardcode_minus_L, )=yes
_LT_TAGVAR(hardcode_minus_L, CXX)=yes
The 2nd parameter is the tag or default tag if it's empty.
Is there any efficient way (maybe by abusing the gcc preprocessor?) to get a set of stripped kernel sources where all code not needed according to .config is left out?
Well got some steps into a solution.
First, one can obtain the used compiler commands by
make KBUILD_VERBOSE=1 | tee build.log
grep '^ gcc' build.log
For now, I select only one gcc command line for further steps. For example the build of kernel/kmod.c, it looks like:
gcc <LIST OF MANY OPTIONS> -c -o kernel/kmod.o kernel/kmod.c
I now remove the option -c, -o ... and add -E, thus disabling compilation and writing preprocessor output to the screen. Further I add -fdirectives-only to prevent macro expansion and -undef to remove the GNU defined macro definitions. -nostdinc to remove the standard c headers is already added by the kernel makefile.
Now includes are still included and thus expanded on the preprocessor output. Thus I pipe the input file through grep removing them: grep -v '#include' kernel/kmod.c. Now only one include is left: autoconf.h is included by the Makefile's command line. This is great as it actually defines the macros used by #ifdef CONFIG_... to select the active kernel code.
The only thing left is to filter out the preprocessor comments and the remaining #defines from autoconf.h by means of grep -v '^#'.
The whole pipe looks like:
grep -v '#include' kernel/kmod.c | gcc -E -fdirectives-only -undef <ORIGINAL KERNEL BUILD GCC OPTIONS WITHOUT -c AND -o ...> - |grep -v '^#'
and the result is a filtered version of kernel/kmod.c containing the code that is actually build into kmod.o.
Questions remain: How to do that for the whole source tree? Are there files that are actually build but never used and stripped at linking?
Kernel Minimization Script :
A project inspired by this question and providing an easy answer...
It contains a Python script that generate a minimized sources code during build time. The new minimized source tree will only contain used sources. (project page)
Info :
The script is tested working with the kernel v4.14.x, however building the kernel one more time from those generated minimized sources require to copy make files and Kconfig files etc... at least we could easily isolate only used source for investigations and development
Usage :
cd /kernel/sources
make
wget https://github.com/Hitachi-India-Pvt-Ltd-RD/minimization/raw/master/minimize.py
export PATH=$PATH:`pwd`
make C=2 CHECK=minimize.py CF="-mindir ../path-to-minimized-source-tree/"
Note & Reminder :
If we are building within and against the targeted machine, we also have the make localmodconfig command that shrink the current config file with only the currently used modules, if used before "Minimization" it will generate further more stripped sources
Compile everything and use atime to find out which files were not used. It might not be very accurate but it's probably worth a try.
I have a program written in C, which is named computeWeight.c and to compile it i use the following code
chaitu#ubuntu:~$ gcc -Wall -o computeWeight computeWeight.c
//to execute it:
chaitu#ubuntu:~$ ./computeWeight
Do i have any mechansim where i can directly use as mentioned below,
chaitu#ubuntu:~$ computeWeight
Should i be changing any permissions on the executable to get this?
You need to add "." to your path. Some people regard this as dangerous, though. See for instance http://www.arsc.edu/support/policy/dotinpath.html .
The $PATH variable define the places where linux would look for executables (try typing echo $PATH in a terminal). You need to put that file in one of those places. One way is to add a bin folder in your home directory, put the executable file there, and add this line (which adds the bin directory in your home folder to the search path) to your .cshrc file so that it'd be executed for every shell:
set PATH = ($PATH $HOME/bin)
With that said I don't think typing ./ is that bad.
export PATH=$PATH:.
I have a makefile that builds and then calls another makefile. Since this makefile calls more makefiles that does the work it doesn't really change. Thus it keeps thinking the project is built and up to date.
dnetdev11 ~ # make
make: `release' is up to date.
How do I force the makefile to rebuild the target?
clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean
build = svn up ~/xxx \
$(clean) \
~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace \
$(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1) \
release:
$(build )
debug:
$(build DEBUG=1)
clean:
$(clean)
install:
cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib
Note: Names removed to protect the innocent
Final Fixed version:
clean = $(MAKE) -f xxx_compile.workspace.mak clean;
build = svn up; \
$(clean) \
./cbp2mak/cbp2mak -C . xxx_compile.workspace; \
$(MAKE) -f xxx_compile.workspace.mak $(1); \
.PHONY: release debug clean install
release:
$(call build,)
debug:
$(call build,DEBUG=1)
clean:
$(clean)
install:
cp ./source/xxx_utillity/release/xxx_util /usr/bin
cp ./dlls/Release/xxxcore.so /usr/lib
The -B switch to make, whose long form is --always-make, tells make to disregard timestamps and make the specified targets. This may defeat the purpose of using make, but it may be what you need.
You could declare one or more of your targets to be phony.
A phony target is one that is not really the name of a file; rather it
is just a name for a recipe to be executed when you make an explicit
request. There are two reasons to use a phony target: to avoid a
conflict with a file of the same name, and to improve performance.
...
A phony target should not be a prerequisite of a real target file; if
it is, its recipe will be run every time make goes to update that
file. As long as a phony target is never a prerequisite of a real
target, the phony target recipe will be executed only when the phony
target is a specified goal
One trick that used to be documented in a Sun manual for make is to use a (non-existent) target '.FORCE'. You could do this by creating a file, force.mk, that contains:
.FORCE:
$(FORCE_DEPS): .FORCE
Then, assuming your existing makefile is called makefile, you could run:
make FORCE_DEPS=release -f force.mk -f makefile release
Since .FORCE does not exist, anything that depends on it will be out of date and rebuilt.
All this will work with any version of make; on Linux, you have GNU Make and can therefore use the .PHONY target as discussed.
It is also worth considering why make considers release to be up to date. This could be because you have a touch release command in amongst the commands executed; it could be because there is a file or directory called 'release' that exists and has no dependencies and so is up to date. Then there's the actual reason...
Someone else suggested .PHONY which is definitely correct. .PHONY should be used for any rule for which a date comparison between the input and the output is invalid. Since you don't have any targets of the form output: input you should use .PHONY for ALL of them!
All that said, you probably should define some variables at the top of your makefile for the various filenames, and define real make rules that have both input and output sections so you can use the benefits of make, namely that you'll only actually compile things that are necessary to copmile!
Edit: added example. Untested, but this is how you do .PHONY
.PHONY: clean
clean:
$(clean)
make clean deletes all the already compiled object files.
If I recall correctly, 'make' uses timestamps (file modification time) to determine whether or not a target is up to date. A common way to force a re-build is to update that timestamp, using the 'touch' command. You could try invoking 'touch' in your makefile to update the timestamp of one of the targets (perhaps one of those sub-makefiles), which might force Make to execute that command.
This simple technique will allow the makefile to function normally when forcing is not desired. Create a new target called force at the end of your makefile. The force target will touch a file that your default target depends on. In the example below, I have added touch myprogram.cpp. I also added a recursive call to make. This will cause the default target to get made every time you type make force.
yourProgram: yourProgram.cpp
g++ -o yourProgram yourProgram.cpp
force:
touch yourProgram.cpp
make
I tried this and it worked for me
add these lines to Makefile
clean:
rm *.o output
new: clean
$(MAKE) #use variable $(MAKE) instead of make to get recursive make calls
save and now call
make new
and it will recompile everything again
What happened?
1) 'new' calls clean.
'clean' do 'rm' which removes all object files that have the extension of '.o'.
2) 'new' calls 'make'.
'make' see that there is no '.o' files, so it creates all the '.o' again. then the linker links all of the .o file int one executable output
Good luck
As abernier pointed out, there is a recommended solution in the GNU make manual, which uses a 'fake' target to force rebuilding of a target:
clean: FORCE
rm $(objects)
FORCE: ;
This will run clean, regardless of any other dependencies.
I added the semicolon to the solution from the manual, otherwise an empty line is required.
As per Miller's Recursive Make Considered Harmful you should avoid calling $(MAKE)! In the case you show, it's harmless, because this isn't really a makefile, just a wrapper script, that might just as well have been written in Shell. But you say you continue like that at deeper recursion levels, so you've probably encountered the problems shown in that eye-opening essay.
Of course with GNU make it's cumbersome to avoid. And even though they are aware of this problem, it's their documented way of doing things.
OTOH, makepp was created as a solution for this problem. You can write your makefiles on a per directory level, yet they all get drawn together into a full view of your project.
But legacy makefiles are written recursively. So there's a workaround where $(MAKE) does nothing but channel the subrequests back to the main makepp process. Only if you do redundant or, worse, contradictory things between your submakes, you must request --traditional-recursive-make (which of course breaks this advantage of makepp). I don't know your other makefiles, but if they're cleanly written, with makepp necessary rebuilds should happen automatically, without the need for any hacks suggested here by others.
If you don't need to preserve any of the outputs you already successfully compiled
nmake /A
rebuilds all
It was already mentioned, but thought I could add to using touch
If you touch all the source files to be compiled, the touch command changes the timestamps of a file to the system time the touch command was executed.
The source file timstamp is what make uses to "know" a file has changed, and needs to be re-compiled
For example: If the project was a c++ project, then do touch *.cpp, then run make again, and make should recompile the entire project.
It actually depends on what the target is. If it is a phony target (i.e. the target is NOT related to a file) you should declare it as .PHONY.
If however the target is not a phony target but you just want to rebuild it for some reason (an example is when you use the __TIME__ preprocessing macro), you should use the FORCE scheme described in answers here.
http://www.gnu.org/software/make/manual/html_node/Force-Targets.html#Force-Targets
On my Linux system (Centos 6.2), there is a significant difference between declaring the target .PHONY and creating a fake dependency on FORCE, when the rule actually does create a file matching the target. When the file must be regenerated every time, it required both
the fake dependency FORCE on the file, and .PHONY for the fake dependency.
wrong:
date > $#
right:
FORCE
date > $#
FORCE:
.PHONY: FORCE
What is the usage of the -I and -L flags in a makefile?
These are typically part of the linker command line, and are either supplied directly in a target action, or more commonly assigned to a make variable that will be expanded to form link command. In that case:
-L is the path to the directories containing the libraries. A search path for libraries.
-l is the name of the library you want to link to.
For instance, if you want to link to the library ~/libs/libabc.a you'd add:
-L$(HOME)/libs -labc
To take advantage of the default implicit rule for linking, add these flags to the variable LDFLAGS, as in
LDFLAGS+=-L$(HOME)/libs -labc
It's a good habit to separate LDFLAGS and LIBS, for example
# LDFLAGS contains flags passed to the compiler for use during linking
LDFLAGS = -Wl,--hash-style=both
# LIBS contains libraries to link with
LIBS = -L$(HOME)/libs -labc
program: a.o b.o c.o
$(CC) $(LDFLAGS) $^ $(LIBS) -o $#
# or if you really want to call ld directly,
# $(LD) $(LDFLAGS:-Wl,%=%) $^ $(LIBS) -o $#
Even if it may work otherwise, the -l... directives are supposed to go after the objects that reference those symbols. Some optimizations (-Wl,--as-needed is the most obvious) will fail if linking is done in the wrong order.
To really grok a makefile, you need to also have a good understanding of the command lines for all of the components of your project's toolchain. Options like -I and -L are not understood by make itself. Rather, make is attempting to create a command line that will execute a tool to transform a prerequisite file into a target file.
Often, that is a C or C++ source file being compiled to an object file, and eventually linked to get an executable file.
In that case, you need to see the manual for your compiler, and especially the bits related to the command line options it understands.
All that said in generic terms, those specific options are pretty standard among compilers and linkers. -I adds a directory to the list of places searched by the compiler for a file named on a #include line, and -L adds a directory to the list of places searched by the linker for a library named with the -l option.
The bottom line is that the "language" of a makefile is a combination of the syntax of the makefile itself, your shell as known to make (usually /bin/sh or something similar), common shell commands (such as rm, cp, install, etc.), and the commands specific to your compiler and linker (e.g. typing gcc -v --help at your shell prompt will give you a nearly complete (and extremely long) list of the options understood by gcc as one starting point).
One thing to note is that these are the options passed to the compiler/linker.
So you should be looking at the compiler man pages/documentation to know their role.