Using execute_process and OUTPUT_VARIABLE in CMake [duplicate] - bash

This question already has answers here:
How to strip trailing whitespace in CMake variable?
(4 answers)
Closed 11 months ago.
I want to add libpqxx library to my project, but find_package doesn't seem work with it. So I decided to manually add pkg-config's output on libpqxx to compiler and linker flags. For some reason this doesn't work (I tried building with CLion and from terminal, they both failed but with different errors). But if I simply insert pkg-config's output manually, then everything works fine.
execute_process (COMMAND bash -c "pkg-config --cflags libpqxx" OUTPUT_VARIABLE libs_cflags)
execute_process (COMMAND bash -c "pkg-config --libs libpqxx" OUTPUT_VARIABLE libs_linker_flags)
# Prints 'flags ='
execute_process (COMMAND bash -c "echo flags = ${CMAKE_CXX_FLAGS}")
# Works fine
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/opt/homebrew/Cellar/libpqxx/7.7.0/include")
# Doesn't work
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${libs_cflags}")
# Prints 'flags=-I/opt/homebrew/Cellar/libpqxx/7.7.0/include'
execute_process (COMMAND bash -c "echo flags = ${CMAKE_CXX_FLAGS}")
# Works fine
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/opt/homebrew/Cellar/libpqxx/7.7.0/lib -lpqxx")
# Doesn't work
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${libs_linker_flags}")

Turns out libs_cflags and libs_linker_flags had trailing whitespaces. Using OUTPUT_STRIP_TRAILING_WHITESPACE for execute_process() solves the problem.

Related

The command with double quotes in the shell cannot be executed

When I execute the following script, it will report an error, but if I manually execute the command of the echo, I will not report an error, they are clearly the same!
I tried to execute this script in Linux, Windows, they all report the same error. Although there is no command MinGW Makefiles on Linux, it will appreciate that even if there is, it will be reported. Because the error prompt is Could not create named generator "MinGW instead of Could not create named generator "MinGW Makefiles"
How can I fix this problem?
#!/bin/bash
compiler_options=(' -G "MinGW Makefiles"')
echo "cmake -S . -B build ${compiler_options}"
cmake -S . -B build ${compiler_options}
# run command
bash test.sh
# errorinfo
CMake Error: Could not create named generator "MinGW
The point of using an array is to avoid cramming all the arguments into a single whitespace-delimited string.
#!/bin/bash
compiler_options=(-G "MinGW Makefiles")
echo "cmake -S . -B build ${compiler_options[*]}"
cmake -S . -B build "${compiler_options[#]}"

Error: no source files when using command substitution [duplicate]

This question already has answers here:
Escaping in makefile
(2 answers)
Closed 1 year ago.
I have the following code:
all: ./source/Listener.java ./source/ServerThread.java ./source/TestClient.java
javac -d target $(find ./source/* | grep .java)
When I run Make, I get this output
javac -d target
error: no source files
Makefile:2: recipe for target 'all' failed
make: *** [all] Error 2
When I run the javac command in bash, it compiles fine. Furthermore, when I run the 'find' section, i get a list of files like I wanted. Additionally, the file paths in line 1 are all accurate.
Any tips?
(I have to use the find function because there are a lot of files in use, and it increases over time. I trimmed it down to 3, but the bug is still there anyway)
As RenaudPacalet said, I had to put an extra $ infront of the second line.
If you want to execute shell commands in a Makefile, use this syntax : $(shell ...)
Warnings :
The default shell is sh (use SHELL macro definion to change it)
Example : SHELL=/bin/bash
The dollar ($) symbol is special into Makefile and into bash script (if you want use it in shell script espace it with double dollar : $$).
Example: $(shell X=a_value; echo $$a_value)
If you want the current process of sub-shell : $(shell echo $$$$) ... ugly, no ?
Do you want really call shell? It's not portable. Assume it.
If you search your sources files or what ever, use wildcard internal make function.
Examples:
all: x.class y.class z.class
x.class: a.java dir_b/b.java dir_c/c.java
#echo "$$^=$^="
#echo "not portable command ..." $(shell find . -name "*.java")
# Better with deps in target definition
SRCS=$(shell find . -name "*.java")
y.class: $(SRCS)
#echo x_my_command $^
# Really better (portable)
SRCS=$(wildcard */*.java *.java)
z.class: $(SRCS)
#echo y_my_command $^
Output:
$^=a.java dir_b/b.java dir_c/c.java=
not portable command ... ./dir_b/b.java ./dir_c/c.java ./a.java
x_my_command dir_b/b.java dir_c/c.java a.java
y_my_command dir_b/b.java dir_c/c.java a.java

why `-R` after `-L` in Makefile

I saw -L/home/kgbook/tools/libiconv/lib -liconv -R/home/kgbook/tools/libiconv/lib when make VERBOSE=1.
What's the meaning of -R, I saw nothing when gcc --help or man gcc. No -R option or argument, neither gcc nor g++.
And why we need -R/home/kgbook/tools/libiconv/lib after -L/home/kgbook/tools/libiconv/lib -liconv?
I'm still confused after saw the question
Where should I insert "etags -R ." in makefile?.

Chisel installation error

While following the tutorial on the Chisel official website for installation, I came to the point where I should test if the installation was done correctly. Doing so yields this error:
set -e -o pipefail; "sbt" -Dsbt.log.noformat=true -DchiselVersion="2.+" "run Parity --genHarness --compile --test --backend c --vcd --targetDir /home/me/chisel-tutorial/generated/examples " | tee /home/me/chisel-tutorial/generated/examples/Parity.out
/bin/bash: sbt: command not found
make: *** [/home/me/chisel-tutorial/generated/examples/Parity.out] Error 127
There is another question regarding the same problem here, where the suggestion to add SHELL=/bin/bash to the Makefile is made. That did not work for me. Another suggestion is to remove set -e -o pipefail: this suggestion actually works but is it OK to remove that option? what does it do?
Edit_1:
I have installed sbt and added its path to the PATH variable.
$ which sbt
/usr/bin/sbt
But still I am getting this error when running make Parity.out
set -e -o pipefail; "sbt" -Dsbt.log.noformat=true -DchiselVersion="2.+" "run Parity --genHarness --compile --test --backend c --vcd --targetDir /home/me/chisel-tutorial/generated/examples " | tee /home/me/chisel-tutorial/generated/examples/Parity.out
/bin/sh: 1: set: Illegal option -o pipefail
make: *** [/home/me/chisel-tutorial/generated/examples/Parity.out] Error 2
If I edit this part of the file suffix.mk:
$(objdir)/%.dot: %.scala
set -e -o pipefail; "$(SBT)" $(SBT_FLAGS) "run $(notdir $(basename $<)) --backend dot --targetDir $(objdir) $(CHISEL_FLAGS)"
$(objdir)/%.out: %.scala
set -e -o pipefail; "$(SBT)" $(SBT_FLAGS) "run $(notdir $(basename $<)) --genHarness --compile --test --backend c --vcd --targetDir $(objdir) $(CHISEL_FLAGS)" | tee $#
By deleting the -o option in the set -e -o pipefail it works, I get the PASSED and [success] message after running $ make Parity.out. So what is going on?
Edit_2:
It is working fine now after I added the SHELL=/bin/bash to the Makefile, so it was first a problem of not having sbt as Nathaniel pointed out then editing the Makefile to include SHELL=/bin/bash.
set -e -o pipefail is a way of making sure that the execution of the bash script both works as expected and that if there is a failure, it halts immediately (rather than at some later stage). Removing it might work - but if there is a failure it might get swallowed and hide the fact it's broken.
But I think your problem lies here, making the other question a bit of a red herring:
/bin/bash: sbt: command not found
Do you have sbt installed on your system? Run which sbt as the user that executes the script. For instance, on my system:
$ which sbt
/opt/local/bin/sbt
If you don't have it on your system, nothing will be returned by running which.
The script clearly needs access to sbt and is failing when it doesn't find it. If you do have it on your system, then there is a mismatch between the user running the script and access to that file. You'll need to post more information about how you're executing the script: in that case it is likely you'll have to update your PATH variables to be able to find the sbt executable.
Given that, after fixing this, you still have a problem, you have to ensure that you're running in bash, and not another terminal type. The reason for this is that bash supports set -o pipefail but a lot of other terminals don't. We suspect this might be the case because of the error messages:
/bin/sh: 1: set: Illegal option -o pipefail
Here we see that /bin/sh (the shell) is being invoked by the program. Use ls -l /bin/sh to determine if your /bin/sh is pointing to a particular shell. If it is not pointed to a bash shell, then you either need to repoint it (be careful! this is probably another question in it's own right), or need to specify to your Scala program to use a specific shell.

Make gcc/g++ use absolute path for warnings when compiling files in pwd

Is there a way to make gcc use the absolute path when printing errors found in files compiled in the current directory?
For instance the following does what I want when print errors:
g++ -I. -I../../.. /home/some/path/somefile.cpp
but I want to achieve the same with something like:
g++ -I. -I../../.. somefile.cpp
I want warnings and errors to be formatting something like:
/home/some/path/somefile.cpp:299:52: warning: some warning
There is no way to do this with gcc itself, but it's trivial with a wrapper script, installed as "gcc", "g++", etc in a directory before /usr/bin in your PATH:
#! /bin/sh
sourcefile="$1"; shift
case "$sourcefile" in
/*) ;;
*) sourcefile="$PWD/$sourcefile" ;;
esac
exec "/usr/bin/${0##*/}" "$sourcefile" "$#"
... provided that you always put the source file first in your compiler invocation (you'll have to tweak your Makefiles).

Resources