Cmake add_custom_command misunderstanding - shell

I'm learning CMake and struggling with learning the: add_custom_command function.
I'm sorry if this is a basic question but the online documentation didn't help me much.
For this snippet:
add_executable (creator creator.cpp)
get_target_property (creator EXE_LOC LOCATION) # get creator.cpp location
add_custom_command(
OUTPUT ./created.cpp # creates 'created.cpp' at the specified path
DEPENDS creator # specifies files on which the command depends
COMMAND ${EXE_LOC} # executes this command
ARGS ./created.cpp
)
add_executable(FOO ./created.c)
I can intuitively realise what's going on there, however, I do not understand why each instruction from the body of add_custom_command is needed. Here is how I understand it (please correct me where I'm wrong):
Executable creator is created in the current working dir using creator.cpp
EXE_LOC variable is used to store the path of the created executable
add_custom_command:
OUTPUT specifies that a created.cpp file will be created in the current
working directory.
DEPENDS: specifies that this newly created .cpp file depends on the
previously created executable. But why do we need to specify this? Is it
mandatory to do so and if not what happens if I don't specify this
COMMAND: ${EXE_LOC}: This I don't understand. I assume when the script
reaches this point some sort of command will be executed. But what exactly is going to get executed here? ./creator maybe? The documentation specifies that:
If COMMAND specifies an executable target (created by ADD_EXECUTABLE) it will automatically be replaced by the location of the executable created at build time.
But I don't really understand this.
ARGS: I don't understand what this is supposed to do and why do we need it.
It really confuses me that we pass the newly created file as an argument to a command whose purpose is to create that particular file.
Please clear this for me if possible.
Thank you for reading my long post.

It is convinient to think about COMMAND option as a command line:
First, you need to type the path to the program to be executed. In given case it is a path to creator executable. Then, you type arguments for given command. In given case, the only argument is a path to the created.cpp file. This is what will be executed:
<path-to-creator-executable> <path-to-cpp-file>
Option
DEPENDS creator
in given case is perfectly described in CMake documentation for add_custom_command:
If DEPENDS specifies any target (created by the add_custom_target(), add_executable(), or add_library() command) a target-level dependency is created to make sure the target is built before any target using this custom command. Additionally, if the target is an executable or library a file-level dependency is created to cause the custom command to re-run whenever the target is recompiled.
In short, this means that before creator executable will be run as specified in the COMMAND option, the executable will be created and updated if needed.

Related

showip: command not found

I am trying to run one of the example from Beej's Guide to Network Programming (https://beej.us/guide/bgnet/), specifically showip.c (The link to the program is here: https://beej.us/guide/bgnet/examples/showip.c). Using gcc, I've typed in
gcc -o showip showip.c
Then ran the program
showip www.example.net
and I get an error showip: command not found on the same directory where the code and the program is compiled at. I'm not sure why this is the case. I've even cloned the code from his GitHub and used makefile to compile the program and yet I'm getting the same error. What exactly am I doing it wrong here?
This is actually problem with how you're running the program.
On Linux systems (unlike Windows systems) an executable in the current directory is not by default searched by the shell for programs to run. If the given program does not contain a path element (i.e. there are no / characters in the name) then only the directories listed in the PATH environment variable are searched.
Since the current directory is not part of your PATH, prefix the command with the directory:
./showip www.example.net
Is the working directory on your path? Likely not.
Try ./showip
Since the program showip is not in your $PATH you have to tell
your shell that it's in the current directory:
./showip
Or add the current directory to your $PATH but it's a less secure
option:
PATH=:$PATH
or
PATH=.:$PATH
and run it as you're trying now:
showip

Command Substitution with Android.mk

I have come across the command in an Android.mk file that I am working with:
include $(DEPENDENCIES_NANOBUFFERS_DIR)/android/jni/include.mk
I understand that $(command) is "command substitution". It runs a command, captures it's output, and inserts that into the command line that contains $( )
However I've searched the entire Android.mk file to find what the command DEPENDENCIES_NANOBUFFERS_DIR stands for and I haven't found any meaning for it.
I know that NANOBUFFERS is a file in my dependencies directory, since I manually searched through all the files contained in my root directory. The is a file named dependencies and within this file is my NANOBUFFERS file. However if DEPENDENCIES_NANOBUFFERS_DIR is not specified explicitly how is the compiler able to find the correct pathway to include.mk? Is this done automatically?
DEPENDENCIES_NANOBUFFERS_DIR occurs in only one other place and that is at the bottom of the Android.mk file.
$(call import-add-path,$(DEPENDENCIES_NANOBUFFERS_DIR)/..)
Can someone please explain how the compiler interprets DEPENDENCIES_NANOBUFFERS_DIR even when this command isn't specfied anywhere in the Android.mk file? Thank you in advance.
This following code links to another Android.mk file which is in a different file which is in a different module
include $(DIFFERENT_DIR)/buildtool/android_common.mk
Within this android_common.mk the variable DEPENDENCIES_NANOBUFFERS_DIR is assigned it's pathway

FreeBSD make creates obj directory

Under FreeBSD, for some odd reason every time I execute a simple Makefile, it tries to create an obj directory under the current PWD.
I thought it might have to do with the default .OBJDIR for FreeBSD make, but setting .OBJDIR: ./ does not change this behavior.
This causes me problems down the line because it conflicts with SConstruct, but I managed to work around that by removing all read/write permissions for ./obj, however I still want to know why every time I run make, it tries to create the ./obj directory if it doesn't exist.
make does not create any ${.OBJDIR} automatically -- something in your Makefiles must be explicitly creating that (or trying to).
Could you post the makefile and/or the output of a make-run?
You can affect the value of the variable by setting MAKEOBJDIRPREFIX or MAKEOBJDIR in the environment or on command-line (neither can be set in /etc/make.conf).
See make(1) for more details.

Compiling PDCurses into ".a", error with mingw command

I'm following this tutorial: https://www.youtube.com/watch?v=mYnfix8ruAo
for compiling PDCurses and linking it to a CodeBlocks project, but I keep getting an error ('mingw32-make' is not recognized as an internal or external command, operable program or batch file.)
The thing is, I definitely have mingw installed properly, and have a path pointing to it in the system environment variables.
http://puu.sh/id6nC/3ab670cbdc.png
In the terminal, I tried the command twice without specifying a target file to make sure it's recognized, and it is. It's not until after I get to the point that I want to build the library that it stops recognizing it as a command for some reason. I'd really appreciate any help.
This isn't a PDCurses issue, it's a PATH issue. The PATH is an environment variable that the command-line shell uses to locate the executables you type as commands, if they aren't in the current directory, or shell built-ins. It's a list of directories, separated by semi-colons. Each directory is checked in turn, until a match is found.
Specifcally, your problem is this line:
path=c:\CodeBlocks\mingw\bin
Apparently, mingw32-make is not in that location. But, since it was found without that line, you clearly don't need the line -- at least not for that. So, just take it out.
Now, if it later turns out that you do need to add \CodeBlocks\mingw\bin to your PATH for some other reason, then the way to do it is like this:
path=%PATH%;c:\CodeBlocks\mingw\bin
This appends your new path to the existing PATH, instead of wiping out the existing PATH and replacing it with that directory alone.

what is the difference between 'make after make clean' and just 'make'?

there are C files in a directory and I have a makefile.
I usually use makefile to compile.
I have been wandering the role of the 'make clean'
'make clean' is just to remove files.
Though I didn't use 'make clean', t
he error and warning was shown up when there were something wrong.
I cannot realize why I need to use 'make clean' whenever I change the source file.
make is a utility is to determine automatically which pieces of a large program need to be recompiled, and issue the commands to recompile them.
To prepare to use make, you must write a file called the makefile that describes the relationships among files in your program, and the states the commands for updating each file.
Once a suitable makefile exists, each time you change some source files, this simple shell command:
make
suffices to perform all necessary recompilations. The make program uses the makefile data base and the last-modification times of the files to decide which of the files need to be updated.
We generally use make clean as a generic way to tell clean up the code.ie; remove all the compiled object files from the source code. You can name it as anything you like.
It's convention only. The convention is that clean will return you to a state where all you have is the "source" files. In other words, it gets rid of everything that can be built from something else (objects, executables, listings and so on).
So make clean ; make is expected to build everything from scratch. And, in fact, you'll often find a rule like:
rebuild: clean all
which will do both steps for you.
You should never have to do a clean unless you're wanting to (for example) copy just the source files somewhere. If you have to do so after editing a file, then your Makefile is not set up correctly.
And, if you make and get an error, you should get exactly the same error if you subsequently make without fixing said error.

Resources