I have two questions:
How do I use CPP (C Preprocessor) with GNU's AS
How do I use "continuation lines" (like some line \ next line)?
For the first, I know you can use .include instead of #include, but #define doesn't work (and I don't know the equivalent). File extension .S is supposed to force it to use the preprocessor, same with g++ -x assembler-with-cpp.
As indicated by #Ciro Santilli, GNU AS does not perform CPP-like preprocessing. For this you need to assemble your file with gcc, like gcc in.S. Doing so enables both the CPP preprocessor and the continuation line symbol.
Otherwise, the AS directive that is roughly equivalent to #define for GNU AS stand-alone is .set (to define new symbols, see AS manual).
Related
Using gcc compiler on linux, I have a C program that used command-line argument (one argument) like
./myprog 0
I want to write a makefile that uses conditional compilation so that if I compile like
make SPECIAL=1
then command-line argument is used.
if I compile without SPECIAL like
make
then command-line argument is ignored even if we enter it.
How to make it possible.
I am using following compilation command
gcc -o myprog myprog.c prog2.c prog3.c
The makefile can be trivial but the real work has to happen in the C code. Something like this, as a minimal example:
#include <stdio.h>
int main(int argc, char **argv, char **envp) {
int i;
#ifndef SPECIAL
argc=1;
argv[1] = NULL;
#endif
for(i=1; i<argc; ++i) {
printf(">>%s<<\n", argv[i]);
}
}
Now, you don't even really need a Makefile for this simple program.
bash$ make CFLAGS=-DSPECIAL=1 -f /dev/null myprog
cc -DSPECIAL=1 myprog.c -o myprog
Having said that, making your build nondeterministic by introducing variations which depend on ephemeral build-time whims is a recipe for insanity. Have two separate targets which create two separate binaries, one with the regular behavior, and the other with the foot-gun semantics.
DEPS := myprog.c prog2.c prog3.c # or whatever your dependencies are
myprog: $(DEPS)
myprog-footgun: CLAGS+=-DSPECIAL=1
myprog-footgun: $(DEPS) # same dependencies, different output file
$(CC) $(CFLAGS) -o $# $^
See Target-specific Variable Values in the GNU Make documentation for details of this syntax.
(Notice that Stack Overflow renders tabs in the Markdown source as spaces, so you will not be able to copy/paste this verbatim.)
I would perhaps in fact reverse the meaning of SPECIAL so that it enables the foot-gun version, rather than the other way around (the original version of this answer had this design, just because I had read your question that way originally).
I mean whether gcc can insert some source code version infor into ELF binary as section or something similar. I do not want to change my source file, but add some info with gcc option in Makefile.
If you don't mind changing your source file just once, add something like this:
const volatile static char version[] = VERSION;
and compile with:
gcc -c -DVERSION='"1.2.3"'
The volatile keeps gcc from removing the string at higher optimization levels.
As written, this won't compile if you forget the -D option, which may be either good or bad depending on your requirements.
You can emit your version info into a text file, then turn that text file into an object file which you then statically link into your executable.
The first step is simple but you have to write some code: a script or something to write your version info in any format you like as a plain text file. Then write a makefile rule to produce say version.o from version.txt, using objcopy. Now you'll have an object file with two useful symbols defined in it: the beginning and end of the textual version info. Add that generated object to your executable, and you'll be able to access the version two ways: by running strings on the binary, or by writing code in the application to print the version string (you'll need to declare the start and end symbols as variables in some header file).
Even if you don't have access to your source anymore, you can link the object with this option:
gcc -Wl,--defsym,VERSION_1_2_3=0 prog.o -o prog
You can check it with hexdump -C prog | less and look for VERSION
Add this to your makefile and be sure to always know when a program was compiled:
BUILD = $(shell date +"%Y%m%d_%H%M%S")
LDLIBS = -Wl,--defsym,BUILD_$(BUILD)=0
With the GNU linker ld You can use
--version-script=version-scriptfile
Read more about the command-line options at:
Using LD, the GNU linker - Options
Read more about creating version scripts at:
Using LD, the GNU linker - Version Script
Let me warn you though, that it is not for the weak-hearted!
I have a file in source tree which name is "time.h", exactly as system "time.h". This cannot be changed. I have encountered a problem with cmake that when I use include_library option it is translated to -I flag which means that my custom "time.h" takes prcedence over system time.h even for <> includes. This is a definiti no-no.
I tried using include_directories (AFTER dir1 dir2) but it still generate -I option instead of expected -idirafter.
I don't think this is a problem with CMake; I believe gcc will always find your "time.h" before the system one, regardless of whether you use quotes or brackets in the #include and regardless of the various options in include_directories. See the entries for -I and -isystem in the gcc documentation
The AFTER option of CMake's include_directories relates only to the order of the directories as listed in the gcc command, it doesn't relate to gcc's -idirafter flag.
It's not a great plan to have your own files with identical names to system files, but if your hands are tied, you could avoid this issue without renaming time.h by qualifying the path for your own includes more fully, so rather than e.g.
CMakeLists.txt: include_directories(${PROJECT_SOURCE_DIR}/src)
header file: #include <time.h> // we want but don't get system one
#include "time.h" // we want and get own custom one
something more like
CMakeLists.txt: include_directories(${PROJECT_SOURCE_DIR})
header file: #include <time.h> // we want and get system one
#include "src/time.h" // we want and get own custom one
An alternative option would be to stick with your current #include setup (using angle brackets for the system time.h and quotes for your own) and not use include_directories at all in the CMakeLists.txt. Instead I think you could replace it with something like:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -iquote ${PROJECT_SOURCE_DIR}/src")
Using -iquote is probably a better option than -idirafter since the directory specified by -idirafter is (in this case incorrectly) treated as a system directory, and as such has warnings suppressed, etc.
If you do go for this choice, it's probably worth commenting the CMakeLists.txt to explain why there is no include_directories to avoid future refactoring reverting back to use the more normal include_directories command.
All in all, your best option if at all possible would be to rename your "time.h" file though.
I have a C program that tries to modify a const string literal. As now I learned that this is not allowed.
When I compile the code with clang test.c the compiler gives no warning. But when I compile it with clang++ test.c it gives a warning:
test.c:6:15: warning: conversion from string literal to 'char *' is deprecated
[-Wdeprecated-writable-strings]
char *s = "hello world";
^
The problem is that it turns out clang++ is just a symbol link of clang:
ll `which clang++`
lrwxr-xr-x 1 root admin 5 Jan 1 12:34 /usr/bin/clang++# -> clang
So my question is how could clang++ behaves differently from clang given that it's a symbol link of clang?
Clang is looking at its argv[0] and altering its behavior depending on what it sees. This is an uncommon and discouraged, but not rare, trick going at least as far back as 4.2BSD ex and vi, which were the same executable, and probably farther.
In this case, clang is compiling your .c file as C, and clang++ is compiling it as C++. This is a historical wart which you should not rely on; use the appropriate compiler command and make sure that your file extension reflects the true contents of the file.
By convention, the name by which a command is invoked is passed as argv[0]; it is not especially unusual for programs to change their behavior based on this. (Historically, ln, cp, and mv were hardlinks to the same executable on Research Unix and used argv[0] to decide which action to do. Also, most shells look for a leading - in argv[0] to decide if they should be a login shell.) Often there is also some other way to get the same effect (options, environment variables, etc.); you should in general use this instead of playing argv[0] games.
There are reasons to do this, but in most cases it's not a good idea to rely on it or to design programs around it.
I have a program, myprogram, which is linked with a static convenience library, call it libconvenience.a, which contains a function, func(). The function func() isn't called anywhere in myprogram; it needs to be able to be called from a plugin library, plugin.so.
The symbol func() is not getting exported dynamically in myprogram. If I run
nm myprogram | grep func
I get nothing. However, it isn't missing from libconvenience.a:
nm libconvenience/libconvenience.a | grep func
00000000 T func
I am using automake, but if I do the last linking step by hand on the command line instead, it doesn't work either:
gcc -Wl,--export-dynamic -o myprogram *.o libconvenience/libconvenience.a `pkg-config --libs somelibraries`
However, if I link the program like this, skipping the use of a convenience library and linking the object files that would have gone into libconvenience.a directly, func() shows up in myprogram's symbols as it should:
gcc -Wl,--export-dynamic -o myprogram *.o libconvenience/*.o `pkg-config --libs somelibraries`
If I add a dummy call to func() somewhere in myprogram, then func() also shows up in myprogram's symbols. But I thought that --export-dynamic was supposed to export all symbols regardless of whether they were used in the program or not!
I am using automake 1.11.1 and gcc 4.5.1 on Fedora 14. I am also using Libtool 2.2.10 to build plugin.so (but not the convenience library.)
I didn't forget to put -Wl,--export-dynamic in myprogram_LDFLAGS, nor did I forget to put the source that contains func() in libconvenience_a_SOURCES (some Googling suggests that these are common causes of this problem.)
Can somebody help me understand what is going on here?
I managed to solve it. It was this note from John Calcote's excellent Autotools book that pointed me in the right direction:
Linkers add to the binary product every object file specified explicitly on the command line, but they only extract from archives those object files that are actually referenced in the code being linked.
To counteract this behavior, one can use the --whole-archive flag to libtool. However, this causes all the symbols from all the system libraries to be pulled in also, causing lots of double symbol definition errors. So --whole-archive needs to be right before libconvenience.a on the linker command line, and it needs to be followed by --no-whole-archive so that the other libraries aren't treated that way. This is a bit difficult since automake and libtool don't really guarantee keeping your flags in the same order on the command line, but this line in Makefile.am did the trick:
myprogram_LDFLAGS = -Wl,--export-dynamic \
-Wl,--whole-archive,libconvenience/libconvenience.a,--no-whole-archive
If you need func to be in plugin.so, you should try and locate it there if possible. Convenience libraries are meant to be just that -- a convenience to link to an executable or lib as an intermediate step.