Fortran compilation output into specific location - compilation

I have a module file in the include directory, which I compile using Makefile from root directory.
$(FC) -c include/my_mod.F90
Compilation works fine, just my module shows up in the root directory instead of the include directory. How can I specify location of the output file?
I am using linux system, and I would like to support both gfortran and ifort.

Thank #albert and #francescalus, the solution is:
ifeq ($(FC),ifort)
FORTFLAGS=-module
else
FORTFLAGS=-J
endif
module:
$(FC) -c include/my_mod.F90 $(FORTFLAGS) include/ -o include/my_mod.o

Related

Including a header from a parent directory

I have a situation where I am given a link to source directory which goes under the parent dir. The contents of the link cannot be modified. The link has a header and .c file. The header file includes a "Config.h" file. The Config.h can only reside in the parent dir because I cannot modify anything under the link. I have to use the sources in the link and compile the parent dir. Here is the directory structure.
ParentDir
|-TestSrc.c
|-TestSrc.h
|-Config.h
|-Makefile
|-LinkToSrcDir
|-Src.c
|-Src.h(#include "Config.h")
My makefile is very straightforward
CC = gcc
INC_DIR = -IParentDir -IParentDir/LinkToSrcDir
CFLAGS = -Wall -Wextra $(INC_DIR)
all: mybin
mybin: TestSrc.o Src.o
$(CC) $(CFLAGS) -o TestSrc.o Src.o
TestSrc.o: TestSrc.c
$(CC) $(CFLAGS) -c TestSrc.c
--- similar code for Src.o ----
Phony: clean (all the usual rm -f)
My problem is, since I cannot modify src.h, the make always complains that Config.h is not found(tried a few different ways). How do I write the Makefile to make src.h look for Config.h in parent dir?
The simplest way is to use a fully-qualified path for the compiler flags:
INC_DIR = -I$(CURDIR)/ParentDir -I$(CURDIR)/ParentDir/LinkToSrcDir
Just to be clear, when the compiler searches for header files using a relative path it always starts with the directory the source file appears in. It doesn't start with the working directory where the compiler is invoked.
From the GCC manual for example:
the preprocessor looks for header files included ... first relative to the directory of the current file
In your case, the current file is LinkToSrcDir/Src.h so all paths will be expanded relative to the directory LinkToSrcDir.
When you say a link above I assume you mean a symbolic link. In that case you may not be able to use something like -I.. because that will give you the parent of the directory linked to.
You pretty much have no alternative but to use a fully-qualified path in your -I options.

How to add multiple Headers files path in a Makefile?

I am trying to compile uleds.c driver and this driver includes multiple files existing under this path :
/opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi/usr/src/kernel/include/linux
I want now to modify my Makefile and add this path so I can compile correctly uleds.c
This is my Makefile :
#CC=arm-poky-linux-gnueabi-gcc -march=armv7-a -marm -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a5 --sysroot=/opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi
#CC="gcc"
obj-m += uleds.o
KERNEL_SOURCE := /opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi/lib/modules/4.14.73-linux4sam-6.0-dirty
default:
${CC} ${KERNEL_SOURCE} uleds.c
clean:
${CC} $(INC) ${KERNEL_SOURCE} clean
Any suggestions for that ? Thank you
This appears to be an attempt at a kbuild file,.
You should not be manually compiling the file yourself using your default rule. Instead, you should be running the kernel's makefile, and have it compile the driver based on obj-m and friends.
Your makefile would look like so:
ifneq ($(KERNELRELEASE),)
ccflags-y += -I some/other/dir
obj-m += uleds.o
else
# default to build against running kernel if KDIR not
# specified:
KDIR ?= /lib/modules/`uname -r`/build
default:
$(MAKE) -C $(KDIR) M=$$PWD
endif
If you call make from the driver's directory, it will in turn call make from your kernel directory, which will know everything about the kernel and will be able to properly build your module.
Notice that by default, the built-in kernel's clean target will remove all generated *.[oas] files, so no need for a special clean target. Also, by default, the kernel's makefile will include its own include directories, so you likely don't need to do anything special for that. In case you do need to include from somewhere else, you can add a -I directive to the ccflags-y as shown in the example.
See Linux Kernel Makefiles and Building External Modules for details.
Simplest is:
${CC} -I/opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi/usr/src/kernel/include/linux uleds.c
Try reading the following to get familiar with other GCC (compiler) options: https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html#Directory-Options

How to force compiler to compile same source file every time used in different shared libraries in cmake? [duplicate]

I have a project directory structure of:
Root
Source
Common
MyFolder
++ My 3 source files and header
When I am building my project it generates 3 to 4 shared libraries. Lib1 compiled using c++98 and others using c++11. Flags are added in CmakeList.txt which is at root.
I need my 3 source files to be compiled for Lib1 and for other Libs as as well. but here what happens is compiler is first compiling my source file for lib using c++11 and then it is trying to use same .o file for Lib1 as well. So for .o file which is generated using c++11 is throwing exception when same is used for c++98 compiled library.
So how do write this in CmakeList.txt such that compiler rather than trying to use same .o file will compile source file again for Lib1(c++98 compiled library)
Is there any flag I can specify so that it won't take precompiled .o file and will compile it again ?
Here flags are not being overridden for different shared libraries but actually same object file by make file is being used for different flags
This is sort of counter to how makefiles and cmake usually work.
Most users consider it really important that make performs an incremental build.
The usual way with makefiles is to do make clean which is supposed to remove any binaries and object files that were created.
However, sometimes I write cmake scripts that use globbing over the source directory to assemble the project. (That means, it says "just grab all *.cpp files in the /src folder and make an executable from them".) A makefile cannot check what files in a directory, so the make build will be broken after I add a new file, and make clean won't fix it -- the whole makefile will need to be regenerated by cmake.
Usually what I do is, I write a simple bash script, named rebuild.sh or something,
#!/bin/bash
rm -rf build
mkdir build
cd build
cmake ..
make -j3
./tests
And I put that in the root of my repository, and add /build to my .gitignore. I call that when I want to do a full rebuild -- it nukes the build directory, so its foolproof. When I want an incremental rebuild, I just type make again in the /build directory.
The rebuild.sh script can also serve a double purpose if you use travis-ci for continuous integration.
Most build system assume the compiled objects remain the same within the same pass. To avoid shooting your foot I would suggest telling the build system they were actually different objects, while still compiled from same source files.
I'm not familiar with cmake but this is how you do with make:
For example you have a a.cpp which you want to compile 2 times for different compiler options:
#include <stdio.h>
int main(int argc, char* argv[]) {
printf ("Hello %d\n", TOKEN);
return 0;
}
And the Makefile would looks like:
SRC := $(wildcard *.cpp)
OBJ_1 := $(patsubst %.cpp,%_1.o,$(SRC))
OBJ_2 := $(patsubst %.cpp,%_2.o,$(SRC))
all: pass1 pass2
pass1: $(OBJ_1)
gcc -o $# $(OBJ_1) -lstdc++
pass2: $(OBJ_2)
gcc -o $# $(OBJ_2) -lstdc++
%_1.o: %.cpp
gcc -DTOKEN=1 -c $< -o $#
%_2.o: %.cpp
gcc -DTOKEN=2 -c $< -o $#
clean:
rm -f $(OBJ_1) $(OBJ_2)
What I do here is generate two different list of object from the same source files, which you can even do the same for dependency(-MMD -MP flags).

Header include path in files generated by `protoc`

When I call protoc like this
protoc --cpp_out=. path/to/test.proto
the files
path/to/test.pb.cc and
path/to/test.pb.h
are generated which is what I want. But, since the cc needs the h, the h is included like this
#include "path/to/test.pb.h"
which is not what I want. The background is that my build tool (scons) calls protoc from the project's root and not from the directory which includes the source files. I found no obvious option in the manpage or the help text.
So my next idea was to consider this as "correct" and adjust my build system, but: The two files are siblings in the directory tree, so when one includes the other, no path is needed. Even compiling by hand fails.
Can someone help me with that?
Doing find-replace on generated files is most likely easier
than reorganization of your build system (use sed command on Linux/unix).
What I ended up doing for my project is as follows:
Create a pb/ directory at the same level as your include/ and src/ directories.
Put your .proto files in there, and create a makefile. Write the following in it:
CXX = g++
CXXFLAGS = -O3
PROTOBF = $(shell find ./ -name '*.proto')
SOURCES = $(subst proto,pb.cc,$(PROTOBF))
OBJECTS = $(subst proto,pb.o,$(PROTOBF))
default: $(OBJECTS)
#echo -n
$(SOURCES): %.pb.cc : %.proto
protoc --cpp_out=. $<
$(OBJECTS): %.pb.o : %.pb.cc
$(CXX) $(CXXFLAGS) -c $< -o $#
Which will essentially generate and build the protobuffer files when invoked.
In your main makefile, simply add the following include path: -Ipb/.
And when including a protocol buffer header, use #include <whatever.pb.h>.
Add the object files generated in pb/ to your linking step. Myself I used:
PB_OBJS = $(shell find pb/ -name '*.pb.o')
And gave that to the linker along with the normal object files in obj/.
Then, you can probably call the pb/ makefile from the main makefile if you want to automate it. The important point is that protoc be called from the pb/ directory or the include will be messed up.
Sorry for the ugly makefiles. At least it works, and I hope this helps you...

Using library paths in makefiles

I have written a makefile like this:
HEADER = -I./cygdrive/c/cpros/kajj/source4
LIBB = -L./cygdrive/c/cpros/kajj/source1 -L./cygdrive/c/cpros/kajj/source2
LIBRA = -larith -ldekk
target : game.o
gcc $(HEADER) $(LIBB) $< -o $# $(LIBRA)
game.o : game.c
gcc -c game.c
I have created my own static library and included the header file path and library path. When I execute my makefile it gives an error saying that
/usr/lib/gcc cannot find -larith -ldekk.
It is pointing to the lib/ directory but it is not over there: -ldekk and -larith are in source1 and source2 files respectively.
How to solve this error?
Instead of -L./cygdrive/c, use -L/cygdrive/c. The dot makes the library path relative from the current directory, i.e. it will look for a cygdrive subfolder of the current folder instead of drive C.
My revised Makefile libraries line is:
LIBS=-L/usr/lib/arm-linux-gnueabihf -lrtlsdr -lpthread -lm
This solved the issue in a Raspberry Pi 4 running the latest Raspbain as of Dec 30, 2019

Resources