Selective compiling in CMake by passing command line arguments - makefile

I have three programs, for example: program_1.cpp, program_2.cpp and program_3.cpp.
As of now, I have separate makefiles to build these programs.
I would like to implement in this in the below manner.
cmake "program_1" # program_1.cpp has to compile
cmake "program_2" # program_2.cpp has to compile
cmake "program_3" # program_3.cpp has to compile
Could you suggest me the ways to achieve this?
[UPDATE]:
I am using a shell script in order to compile the program.
For example
bash build_script.sh build
This would compile the file program_1.cpp and generates the executables.
In the same manner, I would like to implement the below approach.
bash build_script.sh build program_1 -- build program_1.cpp
bash build_script.sh build program_2 -- build program_2.cpp
bash build_script.sh build program_3 -- build program_3.cpp

When generating makefiles, cmake creates a make target for each add_executable() call, so it's only matter of using make target on the makefiles that are generated by cmake:
CMakeLists.txt:
...
add_executable(program_1 prog1.cpp)
add_executable(program_2 prog2.cpp)
add_executable(program_3 prog3.cpp)
And then when comes time to build:
cmake path/to/source/dir
make program_1

Assuming you meant three different targets to compile, you can have a simple makefile:
.PHONY program_1:
program_1:
gcc -o program_1 program_1.cpp
.PHONY program_2:
program_2:
gcc -o program_2 program_2.cpp
.PHONY program_3:
program_3:
gcc -o program_3 program_3.cpp
Then you can simply do:
make program_2
To compile just program_2. This has nothing to do with cmake however.

Related

CMake how to transfer shell command in CMakeLists.txt into Makefile

The problem: i want to echo some info when make makefile, the makefile is generated by CMakeLists.txt, and i don't want to echo the info when cmake CMakeLists.txt, what should i do?
In Makefile, the code is like this:
.build-pre:
#echo
#echo "###########################################################"
#echo "######## Welcome to Prosim Build System ###################"
What should i wirte in the CMakeLists.txt so that i can get like these in MakeFile?
You can use add_custom_target function to create a dummy target that has dependencies set to all other targets causing it to be built first.
You can use the ALL option to make it build every time. However, you will still need to use add_dependencies to make it build before every other target.
Finally, use the command-line tool mode of CMake to make it platform independent. (The COMMENT option of add_custom_target may be enough to show the message).
add_custom_target(display_intro ALL COMMAND cmake -E echo Foo)
# ....
add_executable(your_app ...)
add_dependencies(your_app display_intro)
add_library(your_lib ...)
add_dependencies(your_lib display_intro)
For convenience, you could probably wrap the add_executable and add_dependencies in a function or macro.

`make` doesn't notice modifications in a Rust module - how to better integrate Rust into the build?

In a simple embedded project, i have two files main.rs and module.rs. To build the project, I use something similar to this:
all: main.o
$(CC) main.o $(LDFLAGS)
%.o: %.rs
$(RUSTC) $(RUSTFLAGS) -o ${#} ${<}
If only module.rs is changed, make all won't recompile my Rust code. How can I fix this?
I'm posting a suboptimal self-answer as a first step, but would love to see better ways.
The best way to use Make is to encode every single dependency into the Makefile. That's what gives Make the power to know what to rebuild in order to reach a goal state.
To do this for a C project, you'll often use something like the GCC command line option -M. This brings the compiler into the mix as it's the best tool to parse C source code and understand the dependencies between the
files.
There is actually an equivalent switch for rustc, the Rust compiler: --emit=dep-info. When you run this on a source file, it will output a file with the extension .d, which contains an almost-Makefile-compatible list of dependencies. If you had a main.rs that referenced the module foo.rs, it would output something like:
main.d: main.rs foo.rs
With a bit of sed tweaking you can get this to play nicely. You can then include this in your Makefile:
main.o:
rustc -o $# $<
main.d: main.rs
rustc --emit=dep-info $<
# Add the object file as a rule
gsed 's/:/ $(#:.d=.o):/' -i $#
-include main.d
Here, I've specified main in a few parts, but I believe that you can easily modify them into pattern rules.
The pragmatic solution is to just use Cargo, the Rust build tool and package manager. Let it deal with dependencies (both local modules and other crates).
libbar.dylib: target/debug/libbar.dylib
cp $< $#
.PHONY: target/debug/libbar.dylib
target/debug/libbar.dylib:
cargo build --verbose
Here, I've marked the rule as PHONY, which says "always run this rule". I've added --verbose to have Cargo print out what it is doing so you can verify when things are rebuilt.
I'd recommend dropping off the cp step if you can and instead just use the nested path, but the copy might be needed if other things rely on the current location.
The pattern
%.o: %.rs
is familiar from building C projects, but that's not the only way a target can be written. Specific to the setup above, this would fix the situation:
main.o: main.rs module.rs
$(RUSTC) $(RUSTFLAGS) -o main.o main.rs
A noteworthy difference to the original code is that the names of the inputs is not really what matters for the command. We can generalize this as follows:
main.o: $(wildcard *.rs)
$(RUSTC) $(RUSTFLAGS) -o ${#} ${#:.o=.rs}
This is a start, but it still has some downsides I couldn't get rid of:
The main.o: part is hardcoded. If there are multiple top-level modules to compile, there would be code duplication
All Rust files will be considered for all top-level modules, due to the wildcard. In other words, changing any Rust file will require a full recompilation.

Is there a naming convention for makefile targets and variables

I couldn't find anything in the GNU Makefile Conventions.
This is the implicit naming convention followed by GNU Makefile documentation:
Targets
Target names should use lower case letters. Words are separated with a hyphen - or not separated. E.g.:
test-debug:
$(build_dir)/debug/bin
or
testdebug:
$(build_dir)/debug/bin
Variables
Variables that are not special to make, and that are not inherited from the environment, should be in lowercase. Words should be separated with underscore symbol _. E.g.:
src_dir = $(CURDIR)/src
build_dir = $(CURDIR)/build
References:
Makefile style guide (based on GNU Makefile
documentation)
GNU Makefile Standard Targets
targets: you can find targets like install, install-strip, installcheck
variables: you can read "This includes the directories specified as the values of the variables prefix and exec_prefix" within the install target documentation
The most used (I think) are all, clean, compile, run, install, test, and all common task that you may need to build whatever you're buinding.
You could study makefiles inside big projects such as Linux, Vim, etc, but if you want to get standards into your project you will want to use Autotools as well.
For small projects, I usually use meaningful names based on the context, so I can do something like this:
$make compile (to compile)
$make lib (to create the libraries)
$make link (to link the objects into the executable)
$make run (to run the program)
$make all (to make all of them at once)
and, to make this happen as expected, I have to insert dependencies like:
all: run
run: link
# Instructions for run
link: lib
# Instructions for link
lib: compile
# Instructions for make the lib
compile:
#Instructions for compilation
Makefile's implicit rules use a set of common variable names which are used by convention for explicit rules, such as:
CC: C compiler
CFLAGS: C compiler flags
CXX: C++ compiler (CPP is for C preprocessor)
CXXFLAGS: C++ compiler flags
LDFLAGS: Extra flags for linker, such as -L
LDLIBS: Library flags, such as -lm

Trouble with simple makefile in C

I am somewhat of a beginner in C and have a project due where I need to include a makefile to compile my single file program that uses pthreads and semaphores. My makefile looks like:
# Makefile for pizza program
pizza: pizza.o
gcc -lrt -lpthread -g -o pizza pizza.o
pizza.o: pizza.c
gcc -lrt -lpthread -g -c pizza.o pizza.c
and I keep getting:
make: Nothing to be done for 'Makefile'.
I have done several makefiles before and have never gotten this message. I've tried different semantics in the makefile and have only gotten this same message. And yes, the command is tabbed after the target and dependency line.
Using gcc on tcsh. I have read other makefile posts on SO but I wasn't able to use any of the answers to figure it out for my case.
Any help would be greatly appreciated!
The arguments to make are the targets to be built.
You are running make Makefile which is telling make to try to build the Makefile target.
There is no such target in your makefile, make has no built-in rule that applies to that target and the file exists (and is assumed to be up-to-date) which is what that message is telling you.
To run the default target (by default the first target listed) you can just run make (assuming you are using a default name like Makefile for your makefile).
You can also use the -f argument to make to select an alternate makefile name.
So make -f Makefile will in this case (since Makefile is a default searched name) do the same thing as make.

How to preprocess makefiles

How to show the makefile after it's been preprocessed? For example, if we have two makefiles:
# Makefile
include Makefile2
# Makefile2
a:a.c
gcc -o a a.c
Then <preprocessor> Makefile should give:
a:a.c
gcc -o a a.c
It's similar to what a C preprocessor does (gcc -E). Is there such a makefile preprocessor?
You didn't specify for which make tool you are writing makefile. Assuming that it is GNU make, you can try running makefile with -n (--just-print) option See Command-Line Options chapter here. That will show what make is going to execute without execution (however, the commands needed for evaluation of variables will be executed). This is probably the closest to what you want to see.
This causes make to read the makefile and print every command it would
normally execute to update the target but without executing them.
Apart from that there is $(warning ) function to debug makefiles. You can place it almost to any part in makefile and the following will show you the values of all defined variables in that place:
$(warning Variables HERE: .VARIABLES)

Resources