Linking variables into executable in Makefile - makefile

I like to understand how we can link a global variable into an executable using Makefile.
I compile few C source files and create an executable from it. I compute the md5sum of this executable and want to attach it to another executable and make it available as a global variable in the other executable. By doing this, I can check in the second executable whether the first one has been modified and if it is then I could change some operation.
Although I can do it in the second executable at the beginning of its execution but I would like to stick with this approach as I could learn how to create global variables and link to binary directly in Makefile.

md5sum.c: program_1
echo 'const char md5sum_program_1[] = "'$$(md5sum program_1)'";' > md5sum.c
OBJECTS2 = ... md5sum.o
program_2: ${OBJECTS2}
${CC} -o $# ${CFLAGS} ${OBJECTS2} ${LDFLAGS} ${LDLIBS}
The first line says that the source file md5sum.c depends on the first program, program_1; when md5sum.c does not exist or is older than program_1, the command is executed. The command creates the definition of a global variable md5sum_program_1 and initializes it with the output from md5sum.
The OBJECTS2 macro includes all the object files needed for program_2 plus md5sum.o. The last command links the program.

Related

make is not using -std=c++11 option for g++

I am trying to compile c++ files using make. But, it is not using -std=c++11 flag by default. Whenever I need to compile a program which uses c++11 specific features, I have to explicitly compile it using g++.
So, I want to ask how can I have make automatically use the option -std=c++11 for all my c++ files on my system.
If I need to change some global makefile for g++ , what is the location of the makefile on Linux Mint 18 and what needs to be changed or added?
Or do I need to create a Makefile for myself?
EDIT 1: I am invoking make like make myfile
And there are only .cpp files and their binaries in the directory. I don't have any Makefile in the directory.
EDIT 2: Here, myfile is the name of the c++ file which I want to compile.
When I run make with the -d option, I get the following output (I can not paste all of the output as it is quite long and is exceeding the body size limit so, I am including the screenshots of the output).
Image 1
And this image(2) has some lines from the end.
Image 2
I intentionally made a change in the file "MagicalWord.cpp" so that make finds something to make!
There is no "global makefile" and there is no way to change the default flags for all invocations of make (unless you edit the source code to GNU make and compile it yourself, which is a bad idea in this situation).
In your makefile(s), add the line:
CXXFLAGS += -std=c++11
Assuming you're using the built-in rules for compiling things, or that you're using the standard variables with your own rules, that will do what you need.
If that doesn't work we'll need to see your makefile or at least the rules you use to build your C++ source files (things like the -d output aren't useful here--that would be interesting if files weren't being built, that you thought should be or similar).
Setting a system-wide language for all your C++ projects isn't necessarily a good idea. Instead, define a Makefile that specifies any compiler options you'd like:
CXXFLAGS := -std=c++11 $(CXXFLAGS)
The CXXFLAGS are then passed to your compiler when compiling a C++ program (assuming you're using the default GNU Make rules).
If the Makefile lives in your current working directory, you can now run make target in order to compile a target.cpp file into a target executable.
If the Makefile is in another directory, you must specify the path to it:
make -f path/to/your/Makefile target
If you want to add extra parameters just for one run, you can set an environment variable or a make variable on the command line:
# environment:
CXXFLAGS='-std=c++11' make target
# make variable:
make target CXXFLAGS='-std=c++11'
Any of these will cause the execution of g++ -std=c++11 target.cpp -o target or equivalent.
In theory you can edit your shell profile to export CXXFLAGS='-std=c++11' which will make that environment variable available to all programs you run. In practice, setting compiler options through environment variables tends to cause more problems than it solves.
Of all these solutions, just writing a normal Makefile is by far the easiest approach. That way, all of the build configuration is in one place and completely automated.

How is C++ compiled

I am working on some (very) low level programming but not everything is completely clear to me. I start by creating a .cpp (or .c) file which is run through gcc to create an elf or object file but what is an object file? I get object files when I use the "as" compiler but how are these used and what is the purpose of having an object file when we could have a straight binary?
There is a very clear explanation of this question on the this site. I pasted it down below as well. But I strongly suggest you take a look at the diagram on the website. That will give you a much better high-level understanding of what is going on.
Compiling a source code file in C++ is a four-step process. For example, if you have a C++ source code file named prog1.cpp and you execute the compile command
g++ -Wall -ansi -o prog1 prog1.cpp
the compilation process looks like this:
The C++ preprocessor copies the contents of the included header files into the source code file, generates macro code, and replaces symbolic constants defined using #define with their values.
The expanded source code file produced by the C++ preprocessor is compiled into the assembly language for the platform.
The assembler code generated by the compiler is assembled into the object code for the platform.
The object code file generated by the assembler is linked together with the object code files for any library functions used to produce an executable file.
By using appropriate compiler options, we can stop this process at any stage.
To stop the process after the preprocessor step, you can use the -E option:
g++ -E prog1.cpp
The expanded source code file will be printed on standard output (the screen by default); you can redirect the output to a file if you wish. Note that the expanded source code file is often incredibly large - a 20 line source code file can easily produce an expanded file of 20,000 lines or more, depending on which header files were included.
To stop the process after the compile step, you can use the -S option:
g++ -Wall -ansi -S prog1.cpp
By default, the assembler code for a source file named filename.cpp will be placed in a file named filename.s.
To stop the process after the assembly step, you can use the -c option:
g++ -Wall -ansi -c prog1.cpp
By default, the assembler code for a source file named filename.cpp will be placed in a file named filename.o

Separate compilation

I am learning C++ by S. Lippman 5th edition book. I reached chapter 6 where I can't understand separate compilation. In book is written "As an example, assume that the definition of our fact function is in a file named
fact.cc and its declaration is in a header file named Chapter6.h. Our fact.cc
file, like any file that uses these functions, will include the Chapter6.h header. We’ll
store a main function that calls fact in a second file named factMain.cc. To
produce an executable file, we must tell the compiler where to find all of the code we
use. We might compile these files as follows:
$ CC factMain.cc fact.cc # generates factMain.exe or a.out
$ CC factMain.cc fact.cc -o main # generates main or
main.exe
Here CC is the name of our compiler, $ is our system prompt, and # begins a
command-line comment. We can now run the executable file, which will run our main
function"
Where I have to compile these files($ CC factMain.cc fact.cc # generates factMain.exe or a.out
)? I use Codeblocks 16.01. Thank you.
The commands:
$ CC factMain.cc fact.cc # generates factMain.exe or a.out
or
$ CC factMain.cc fact.cc -o main # generates main or main.exe
are what you enter into your terminal to compile all the files that you specify in the command-line prompt (in your case factMain.cc and fact.cc).
The -o flag at the end of your second command signifies the name that your executable will have. (If you do not have a -o flag then the name of your executable will be a.out)
In order to find your executable, just look in your present working directory within terminal.
The command for this is:
ls
You should find your executable listed amongst all the files that are in that working directory.

Makefile -L command

If I have this line in the make file:\
libpqxx_Libs = -L/share/home/cb -lpqxx-2.6.9 -lpq
Does this indicate the compiler to use the lpqxx-2.6.9.so shared object file or does this indciate the compiler to use all the .so in the foler lpqxx-2.6.9? Or is this something else altogether?
Thanks for the help!
-L in this context is an argument to the linker, that adds the specified directory to the list of directories that the linker will search for necessary libraries, e.g. libraries that you've specified using -l.
It isn't a makefile command, even though it's usually seen in makefiles for C projects.
The -L is actually not a makefile command (as you state it in the title of your question).
What actually happens in this line is an assignment of a value to the variable libpqxx_Libs -- nothing more and nothing less. You will have to search in your makefile where that variable is used via $(libpqxx_Libs) or ${libpqxx_Libs}. That is most likely as a argument in a link command, or a compile command that includes linking.
In that context, the meaning of -L and -l can be found in, for example, the gcc man pages, which state that
-llibrary
Use the library named library when linking.
The linker searches a standard list of directories for the li-
brary, which is actually a file named `liblibrary.a'. The linker
then uses this file as if it had been specified precisely by
name.
The directories searched include several standard system direc-
tories plus any that you specify with `-L'.

Make gcc put relative filenames in debug information

The project I'm compiling uses CMake, which loves absolute pathnames.
When I compile with debugging information enabled, gcc puts those long names into .debug_str sections, which is bad for debugging. I'd like to have short relative-to-project-root pathnames there instead.
Is there some option to tell gcc to strip some part of pathname before emitting debug data? Or, maybe, there is some tool that could do that on compiled binaries?
I've tried using SET(CMAKE_USE_RELATIVE_PATHS ON) (which seems to be frowned upon by devs) option, but as I'm using out-of-source builds, pathnames are still not in the form I'd want them to be. I.e. they're ./../src/mod_foo/foo.c instead of mod_foo/foo.c.
You can use the -fdebug-prefix-map flag to remap the debugging information paths. For example, to make the paths relative to the build location use: -fdebug-prefix-map=/full/build/path=.
You can set the RULE_LAUNCH_COMPILE property of a CMake target to have CMake invoke a shell script which transforms the source file path to a project relative path before invoking gcc. Use the CMake function configure_file to generate a shell script which knows about the PROJECT_SOURCE_DIR and PROJECT_BINARY_DIR of your project.
In your outermost CMakeLists.txt add the following code:
configure_file(
"${PROJECT_SOURCE_DIR}/gcc_debug_fix.sh.in"
"${PROJECT_BINARY_DIR}/gcc_debug_fix.sh"
#ONLY)
add_executable (MyExecutable ...)
set_target_properties(MyExecutable PROPERTIES
RULE_LAUNCH_COMPILE "${PROJECT_BINARY_DIR}/gcc_debug_fix.sh")
The following template shell script gcc_debug_fix.sh.in needs to go to the root directory of the CMake project:
#!/bin/sh
PROJECT_BINARY_DIR="#PROJECT_BINARY_DIR#"
PROJECT_SOURCE_DIR="#PROJECT_SOURCE_DIR#"
# shell script invoked with the following arguments
# $(CXX) $(CXX_DEFINES) $(CXX_FLAGS) -o OBJECT_FILE -c SOURCE_FILE
# extract parameters
SOURCE_FILE="${#: -1:1}"
OBJECT_FILE="${#: -3:1}"
COMPILER_AND_FLAGS=${#:1:$#-4}
# make source file path relative to project source dir
SOURCE_FILE_RELATIVE="${SOURCE_FILE:${#PROJECT_SOURCE_DIR} + 1}"
# make object file path absolute
OBJECT_FILE_ABSOLUTE="$PROJECT_BINARY_DIR/$OBJECT_FILE"
cd "$PROJECT_SOURCE_DIR"
# invoke compiler
exec $COMPILER_AND_FLAGS -c "${SOURCE_FILE_RELATIVE}" -o "${OBJECT_FILE_ABSOLUTE}"
The shell script uses the information from the variables PROJECT_BINARY_DIR and PROJECT_SOURCE_DIR to transform the path of the source file to a path relative to the project root and the object file's path to an absolute path. Because gcc gets passed a project relative path now, .debug_str should use that path, too.
The following caveats apply:
Be sure to set the executable bit of gcc_debug_fix.sh.in.
For the script to work CMAKE_USE_RELATIVE_PATHS has to set to OFF again.
The script makes assumptions about the location of the file paths on the command line. This may not work if CMake uses a different rule to invoke the compiler. A more robust solution would be to scan the script arguments for the -o and -c flags.
If I really couldn't fix the make file/tool to do this properly, I would write a wrapper script for gcc that recognises absolute pathnames and converts then to relative ones.
It might look something like this in bash:
#!/bin/bash
out=()
for arg; do
out=("${out[#]}" $(echo "$arg" | sed 's:/my/absolute/directory/:../:'))
done
exec gcc "${out[#]}"
If your source directory has subdirectories then you'll need to handle those carefully, but the above should work for a flat source directory. I've not tested it though, and I wouldn't be surprised if I've got the quoting wrong, but that'll only be a problem if you have pathnames with spaces in. It also doesn't handle parameters like -I/whatever/include, but you can fix that.

Resources