I have the following makefile (Makefile.certify) and when I execute:
make -f Makefile.certify
It gives me a:
/bin/sh: line 23: -o: command not found
PROG=certify
TMP=/var/tmp
ARCH=x86_64
_CC=/bin/cc
all: ${PROG}
${PROG}: ${ARCH}
#for mode in $? ; do \
case $${mode} in \
i386) \
CC="${_CC} -g -D__x86"; \
;; \
i386-f64) \
CC="${_CC} -D_FILE_OFFSET_BITS=64 -g -D__x86";\
;; \
amd64) \
CC="${_CC} -m64 -g -D__x86 -D__ia64 -D__GNUC";\
;; \
*) \
;; \
esac; \
$${CC} -o ${TMP}/$${mode}/$# ${TMP}/$#.c; \
done
I don't really use makefiles or c, but I have to deal with this one.
My questions are:
Why does for loop need a # prefix?
What is the $? in the for loop?
What would be a possible execution of this makefile? Obviously it tries to compile my certify.c file based on the architecture of the system executing or something like this, but I fail to see how it will choose either i386 or amd64 etc.
I am using an x86 system running RHEL.
# prefix is used for suppressing command print by make. If it is not present, make will print command before execution to output.
You can remove it and see the difference.
$? is the dependency list. In your particular case ARCH is defined as a single entry "x86_64". So $? will be expanded into that value. But you can try to modify ARCH value in the following way:
ARCH=x86_64 i386
It tries to build certify binary for a given architecture from cerfify.c source file. Each binary will be located in own sub-directory:
/var/tmp/{i386|x86_64|i386_f64}/certify
# is used to suppress the normal 'echo' of the command that is executed. Using it in the for loop is also new to me (does removing it change anything in the output?)
$? is one of the makefile automatic variables, this one means "The names of all the prerequisites that are newer than the target, with spaces between them"
It will iterate through $?, read above
Edit:
Example of $?
targetfile : firstfile secondfile thirdfile
cat $? > $#
if targetfile is older than all the other 3 files, the makefile will concatenate the contents of firstfile, secondfile and thirdfile together in targetfile.
Related
I have a directory where I have some C program files and a Makefile with executables of those C files. I can simply run this to remove all the executable at once in rm !(*.c|Makefile).
But when i am adding this to my makefile
CFLAGS= -Wall -g -lm
SHELL=/bin/bash
careful:
echo "nothing"
clean:
rm -i !(*.c|Makefile)
I am getting this error while executing the command
/bin/bash: -c: line 1: syntax error near unexpected token `('
/bin/bash: -c: line 1: `rm -i !(*.c|Makefile)'
make: *** [Makefile:8: clean] Error 2
I am not too knowledgeable about Bash syntax but I know that () is treated as a subshell, I think that's why I can't run rm (*.c) directly in the terminal because *.c is not a command (or any valid syntax). But running rm -i !(*.c) works in the terminal. So I guess !() is treated differently in Bash.
My assumption on all this: in Makefile when I am running make clean it is treating !(*.c|Makefile), differently than in normal terminal, or somehow it is disregarding ! in !(*.c|Makefile)
So my questions are:
Are !() and () treated differently in Bash?
Why does !(wildcard) work in the terminal but not in my Makefile
How can I make it work in the Makefile?
The Bash-specific extended globbing patterns are not enabled out of the box for noninteractive shells.
!(...) is purely part of this wildcard syntax, and has nothing with subshells to do.
Probably a better solution anyway is to refactor this so you don't depend on Bash.
.PHONY: clean
clean:
rm -i $(filter-out $(wildcard *.c) Makefile,$(wildcard *))
The Bash Reference Manual doesn't have a good anchor to link to, but the extended globbing syntax available with extglob is described in the section on Pattern Matching
If you really wanted to, you could shopt -s extglob in your Makefile, too, but this gets rather complicated as you will have to hide the statement from the parser until the shell is configured to understand this syntax. For example,
.PHONY: clean
clean:
shopt -s extglob; \
eval 'rm -i !(*.c|Makefile)'
Notice also how shopt and eval need to be on the same logical line, as make out of the box executes each recipe line in a separate new shell instance (though you can change that with .ONESHELL)
I am trying to compile a file using an ARM (RVCT 3.1) compiler.
The makefile looks something like this (pasting extract)
AS = armasm
LD = armlink
CC = armcc
TCC = armcc
#TCC = tcc
CPP = armcpp
TCPP = tcpp
AR = armar
NM = nm
ifeq ($(TERM),cygwin)
RM = rm
RM_OPT = -rf
else
RM = del
RM_OPT =
endif
# Standard CFLAGS
ENDIAN := --li
CFLAGS := -g -O2 -Otime --forceinline --cpu ARM7EJ-S $(ENDIAN) \
--apcs /interwork --fpu softvfp --fpmode ieee_fixed \
--bss_threshold=0 --split_sections \
--md --no_depend_system_headers --depend_format=unix
ASFLAGS := --keep -g --cpu ARM7EJ-S $(ENDIAN) \
--apcs /interwork \
--md
LINKFLAGS := --debug --remove --scatter $(BUILD).mem \
--map --symdefs $(BUILD).sym --keep SDK_Callback.o\(*\) \
--list linker.txt --info sizes,totals,veneers,unused \
--errors output.txt --entry SDK_Main \
--elf --output
ARFLAGS := -ru
when I run the make command I get an error like this
Assembling SDK_Callback.s......
armasm --keep -g --cpu ARM7EJ-S --li --apcs /interwork --md -o SDK_Callback.o SDK_Callback.s
make: *** No rule to make target `C:/Program', needed by `xxx_SDK.o'. Stop.
Generating scatter loading file.
make: del: Command not found
make: [makefile:140: clean] Error 127 (ignored)
my compiler is located at "C:\Program Files\ARM"
and I can even see that it is installed properly.
$ armcc --vsn
ARM/Thumb C/C++ Compiler, RVCT3.1 [Build 1055]
For support see http://www.arm.com/support/
Software supplied by: ARM Limited
based on ifeq ($(TERM),cygwin) condition, it should detect the shell to be cygwin (which I am using) and use rm- rf for delete operation and also follow the unix path and line endings. But looking at the errors looks like the makefile is still running under a windows shell (del is used instead of rm -rf)
Is there some configuration under cygwin that has changed or needs to be enabled for it to work as a unix shell?
I have already downloaded the whole 'devel' section of cygwin, just to be sure including 'make' and 'g++' options.
I have also included the cygwin path in the environment variables.
One more clue I have is, it used to work fine on my older system, I started seeing the problem after I switched to a new system and installed everything (cygwin, compiler) again.
Is this a cygwin problem? or the makefile?
Any help is appreciated thanks !
Update: I changed ifeq ($(TERM),cygwin) to ifeq ($(TERM),xterm) and it worked, looks like the terminal name was changed at some point of cygwin updates.
I want to compile mex files without installing xcode, using only Command Line Tools (from apple developer center).
Apple Command Line Tools install the compiler and adds standard libraries and headers to the system in a package much smaller than xcode (which is several GBs).
Running mex on linux is possible - I see no reason why matlab mex should require the huge SDKs required for macos. A long evening of trial and error and hacking configuration files hasn't helped. Does anyone have a minimal working example of how to compile a mex file outside matlab, or a simple way to use mex without having xcode installed?
Best Regards, Magnus
Well, I have another option here:
Edit the files under /Applications/MATLAB_R2016b.app/bin/maci64/mexopts (probably there should be 3.xml file, all needs the same modification).
Locate the <XCODE_AGREED_VERSION> portion, comment the whole xml tag, e.g. wrap them with <!-- and --> like this:
<!--XCODE_AGREED_VERSION>
<and diagnostic="Xcode is installed, but its license has not been accepted. Run Xcode and accept its license agreement." >
<or>
<cmdReturns name="defaults read com.apple.dt.Xcode IDEXcodeVersionForAgreedToGMLicense"/>
<cmdReturns name="defaults read /Library/Preferences/com.apple.dt.Xcode IDEXcodeVersionForAgreedToGMLicense"/>
</or>
<cmdReturns name="
agreed=$$
if echo $agreed | grep -E '[\.\"]' >/dev/null; then
lhs=`expr "$agreed" : '\([0-9]*\)[\.].*'`
rhs=`expr "$agreed" : '[0-9]*[\.]\(.*\)$'`
if echo $rhs | grep -E '[\."]' >/dev/null; then
rhs=`expr "$rhs" : '\([0-9]*\)[\.].*'`
fi
if [ $lhs -gt 4 ] || ( [ $lhs -eq 4 ] && [ $rhs -ge 3 ] ); then
echo $agreed
else
exit 1
fi
fi" />
</and>
</XCODE_AGREED_VERSION -->
Some notes:
These files are read only by default, you need to issue sudo chmod
644 * in that directory
after comment out all necessary files, issue this command in matlab:
mex -setup C++
Then you are done
After spending more time, I wound up learning more stuff and answering my own question. I'll post my solution here if anyone else needs it in the future.
Make sure the cord is connected to your computer and that MATLAB is installed, and also install the command line tools from apple. Then call the following makefile to compile arrayProduct.c (comes with matlab) from the terminal as follows:
make mex=arrayProduct
Put this makefile code in the same folder in a file called makefile(edit to your own needs if you have to):
all:
clang -c\
-DMX_COMPAT_32 \
-DMATLAB_MEX_FILE \
-I"/Applications/MATLAB_R2016b.app/extern/include" \
-I"/Applications/MATLAB_R2016b.app/simulink/include" \
-fno-common \
-arch x86_64 \
-fexceptions \
-O2 \
-fwrapv \
-DNDEBUG \
"/Applications/MATLAB_R2016b.app/extern/version/c_mexapi_version.c" \
$(mex).c
clang \
-Wl,-twolevel_namespace \
-undefined error \
-arch x86_64 \
-bundle \
-Wl,-exported_symbols_list,"/Applications/MATLAB_R2016b.app/extern/lib/maci64/mexFunction.map" \
$(mex).o \
c_mexapi_version.o \
-O \
-Wl,-exported_symbols_list,"/Applications/MATLAB_R2016b.app/extern/lib/maci64/c_exportsmexfileversion.map" \
-L"/Applications/MATLAB_R2016b.app/bin/maci64" \
-lmx \
-lmex \
-lmat \
-lc++ \
-o $(mex).mexmaci64
The above makefile is a bare minimum working example, you should edit it to comply with your requirements.
Edit:
Option 2
You can make MATLAB understand how to use the Command Line Tools by editing the xml file containing the compiler options instead. Open the file located at
/User/username/Library/Application Support/MathWorks/MATLAB/R2016b/mex_C_maci64.xml
Remove all compiler and linker options related to ISYSROOT. This will make the compiler search for header files in /usr/include etc instead of in the SDK-folder in XCode.
I fully understand you and I'm a big advocate of non-using the enormous Xcode. From my saver here, run the following to trick mex into seeing an accepted license (no sudo needed).
Here I use the current version 13.0 at the time of writing, to be adapted.
defaults write com.apple.dt.Xcode IDEXcodeVersionForAgreedToGMLicense 13.0
I'm trying to cross compile OpenSSL for PowerPC with the FIPS module. My build host's architecture is not PowerPC. I was able to cross compile the FIPS module just fine. However, when I run make on openssl, during the linking phase, it tries to execute certain binaries to run tests. The issue is that those binaries are produced for the target architecture and, as a result, I get the error "cannot execute binary file". Is there a way to produce executables of these tests on the host architecture rather than the target architecture? Should I be handling this process differently? Here are the following commands I used to build openssl. I replaced certain directories with DIR_HIDDEN.
export FIPS_DIRECTORY="$PWD/../../openssl-fips/tgt/linux-ppc603e/"
export cross="DIR_HIDDEN/powerpc-linux-gnu-"
make clean || exit 1
make dclean || exit 1
./Configure --prefix=$PWD/../tgt/linux-ppc603e linux-ppc fips --with-fipsdir=${FIPS_DIRECTORY}
make depend || exit 1
make CC="$FIPS_DIRECTORY/bin/fipsld" RANLIB="${cross}ranlib" AR="${cross}ar r" LD="$FIPS_DIRECTORY/bin/fipsld" FIPSLD_CC="${cross}gcc" HOSTCC="/usr/bin/gcc" || exit 1
make install || exit 1
I get the following error during the make command:
shlib_target=; if [ -n "" ]; then \
shlib_target="linux-shared"; \
elif [ -n "libcrypto" ]; then \
FIPSLD_CC="/DIR_HIDDEN/openssl/openssl-1.0.1i/../../openssl-fips/tgt/linux-ppc603e//bin/fipsld"; CC=/DIR_HIDDEN/openssl/openssl-1.0.1i/../../openssl-fips/tgt/linux-ppc603e//bin/fipsld; export CC FIPSLD_CC; \
fi; \
LIBRARIES="-L.. -lssl -L.. -lcrypto" ; \
make -f ../Makefile.shared -e \
APPNAME=openssl OBJECTS="openssl.o verify.o asn1pars.o req.o dgst.o dh.o dhparam.o enc.o passwd.o gendh.o errstr.o ca.o pkcs7.o crl2p7.o crl.o rsa.o rsautl.o dsa.o dsaparam.o ec.o ecparam.o x509.o genrsa.o gendsa.o genpkey.o s_server.o s_client.o speed.o s_time.o apps.o s_cb.o s_socket.o app_rand.o version.o sess_id.o ciphers.o nseq.o pkcs12.o pkcs8.o pkey.o pkeyparam.o pkeyutl.o spkac.o smime.o cms.o rand.o engine.o ocsp.o prime.o ts.o srp.o" \
LIBDEPS=" $LIBRARIES -ldl" \
link_app.${shlib_target}
make[2]: Entering directory `/DIR_HIDDEN/openssl/openssl-1.0.1i/apps'
( :; LIBDEPS="${LIBDEPS:--L.. -lssl -L.. -lcrypto -ldl}"; LDCMD="${LDCMD:-/DIR_HIDDEN/openssl/openssl-1.0.1i/../../openssl-fips/tgt/linux-ppc603e//bin/fipsld}"; LDFLAGS="${LDFLAGS:--DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DB_ENDIAN -DTERMIO -O3 -Wall -DOPENSSL_BN_ASM_MONT -I/DIR_HIDDEN/openssl/openssl-1.0.1i/../../openssl-fips/tgt/linux-ppc603e//include -DSHA1_ASM -DSHA256_ASM -DAES_ASM}"; LIBPATH=`for x in $LIBDEPS; do echo $x; done | sed -e 's/^ *-L//;t' -e d | uniq`; LIBPATH=`echo $LIBPATH | sed -e 's/ /:/g'`; LD_LIBRARY_PATH=$LIBPATH:$LD_LIBRARY_PATH ${LDCMD} ${LDFLAGS} -o ${APPNAME:=openssl} openssl.o verify.o asn1pars.o req.o dgst.o dh.o dhparam.o enc.o passwd.o gendh.o errstr.o ca.o pkcs7.o crl2p7.o crl.o rsa.o rsautl.o dsa.o dsaparam.o ec.o ecparam.o x509.o genrsa.o gendsa.o genpkey.o s_server.o s_client.o speed.o s_time.o apps.o s_cb.o s_socket.o app_rand.o version.o sess_id.o ciphers.o nseq.o pkcs12.o pkcs8.o pkey.o pkeyparam.o pkeyutl.o spkac.o smime.o cms.o rand.o engine.o ocsp.o prime.o ts.o srp.o ${LIBDEPS} )
/DIR_HIDDEN/openssl/openssl-1.0.1i/../../openssl-fips/tgt/linux-ppc603e//bin/fipsld: line 185: ./openssl: cannot execute binary file
make[2]: *** [link_app.] Error 126
When invoking the make command again and again, I get the same error but for all the applications located in the /test directory of the openssl tarball. Examples include bntest, ectest, and ecdhtest.
I received a similar error when I was cross compiling the FIPS module, but I was able to resolve that by including the host compiler in the HOSTCC variable. A similar trick did not work for the openssl compilation.
Any guidance would be appreciated. Thanks!
I was able to modify the make command to get the process to complete. I was missing the FIPS_SIG environment variable, which points to the incore script. The make command is now:
make FIPS_SIG=$PWD/`find ../../openssl-fips/ -iname incore` CC="$FIPS_DIRECTORY/bin/fipsld" RANLIB="${cross}ranlib" AR="${cross}ar r" LD="$FIPS_DIRECTORY/bin/fipsld" FIPSLD_CC="${cross}gcc"
I still see prints to console that indicate that openssl cannot be executed, but these are warnings and don't halt the makefile. Not really sure why or how this fixed the problem, but I'll take it.
Is it possible to compile a stream of data rather than compiling a .c file using gcc? for example, is it possible that instead of having my code stored in any xyz.c file, I can directly compile the code?
Use gcc options -x and -
$ echo -e '#include <stdio.h>\nmain(){puts("Hello world");return 0;}' | gcc -xc -ogarbage - && ./garbage && rm garbage
Hello world
The single line command above is made up of the following parts:
echo -e '#include <stdio.h>\nmain(){puts("Hello world");return 0;}' # "source"
| # pipe
gcc -xc -ogarbage - # compile
&& # and
./garbage # run
&& # and
rm garbage # delete
This may answer you question, though it is rarely useful.
You can create a file, stream the code into it, then create another process(that is, the compiler) giving it the file as an argument. Then create another process(that is, the linker) and it will create an exe for you. And finally you can launch that exe as a new process. But why?!:)