I'm building a little OpenWRT application and I want to statically link a library to it.
EDIT: This happens with other libraries as well, not only libcurl.
I'm getting this error while building it:
make[3]: Entering directory `/home/md/work/openwrt/build_dir/target-mips_r2_uClibc-0.9.33.2/app'
mips-openwrt-linux-uclibc-gcc -c -Os -pipe -mips32r2 -mtune=34kc -mno-branch-likely -fno-caller-saves -fhonour-copts -Wno-error=unused-but-set-variable -msoft-float -Wall -Werror main.c -o main.o
mips-openwrt-linux-uclibc-gcc -Os -pipe -mips32r2 -mtune=34kc -mno-branch-likely -fno-caller-saves -fhonour-copts -Wno-error=unused-but-set-variable -msoft-float -Wall -Werror -L/home/md/work/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib -L/home/md/work/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/lib -L/home/md/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/usr/lib -L/home/md/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib -Wl,-Bstatic -lcurl main.o -o app
/home/md/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/gcc/mips-openwrt-linux-uclibc/4.6.4/../../../../mips-openwrt-linux-uclibc/bin/ld: cannot find -lgcc_s
/home/md/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/gcc/mips-openwrt-linux-uclibc/4.6.4/../../../../mips-openwrt-linux-uclibc/bin/ld: cannot find -lgcc_s
collect2: ld returned 1 exit status
make[3]: *** [app] Error 1
It's weird, because I have libgcc_s.so on the search path:
stormbreaker:openwrt> find . -name libgcc_s.*
./build_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/uClibc-0.9.33.2/libc/sysdeps/linux/common/libgcc_s.h
./build_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/gcc-linaro-4.6-2012.12-final/gcc/libgcc_s.so
./build_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/gcc-linaro-4.6-2012.12-final/gcc/libgcc_s.so.1
./build_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/gcc-linaro-4.6-2012.12-final/mips-openwrt-linux-uclibc/libgcc/libgcc_s.so
./build_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/gcc-linaro-4.6-2012.12-final/mips-openwrt-linux-uclibc/libgcc/libgcc_s.so.1
./build_dir/target-mips_r2_uClibc-0.9.33.2/toolchain/ipkg-ar71xx/libgcc/lib/libgcc_s.so.1
./build_dir/target-mips_r2_uClibc-0.9.33.2/toolchain/libgcc_s.so.1
./staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/libgcc_s.so
./staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/libgcc_s.so.1
./staging_dir/target-mips_r2_uClibc-0.9.33.2/root-ar71xx/lib/libgcc_s.so
./staging_dir/target-mips_r2_uClibc-0.9.33.2/root-ar71xx/lib/libgcc_s.so.1
I tried some hacks with -rpath and -rpath-link, but got the same result. As far as I know, libcurl doesn't need libgcc_s.
I created a simple case to reproduce this:
The relevant part of openwrt/package/app/Makefile:
TARGET_CFLAGS += -Wall -Werror
TARGET_LIBS = -Wl,-Bstatic -lcurl
define Build/Compile
CC="$(TARGET_CC)" \
CFLAGS="$(TARGET_CFLAGS)" \
LDFLAGS="$(TARGET_LDFLAGS)" \
LIBS="$(TARGET_LIBS)" \
$(MAKE) -C $(PKG_BUILD_DIR)
endef
openwrt/package/app/src/Makefile:
APP = app
SOURCES = $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)
$(APP): $(OBJECTS)
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(OBJECTS) -o $(APP)
# Objects
%.o: %.c
$(CC) -c $(CFLAGS) $< -o $#
The application itself is a single file:
#include <stdio.h>
#include <curl/curl.h>
int main (void)
{
curl_global_init(CURL_GLOBAL_ALL);
printf("Ok!\n");
return 0;
}
Increasing the verbosity of the linker (using -Wl,--verbose=99) gave me these clues:
...
attempt to open /home/md/work/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33/usr/lib/libgcc_s.a failed
attempt to open /home/md/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33/lib/gcc/mips-openwrt-linux-uclibc/4.6.3/libgcc_s.a failed
attempt to open /home/md/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33/lib/gcc/mips-openwrt-linux-uclibc/4.6.3/../../../../mips-openwrt-linux-uclibc/lib/libgcc_s.a failed
attempt to open /home/md/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33/mips-openwrt-linux-uclibc/bin/../../../toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33/usr/local/lib/libgcc_s.a failed
attempt to open /home/md/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33/mips-openwrt-linux-uclibc/bin/../../../toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33/lib/libgcc_s.a failed
attempt to open /home/md/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33/mips-openwrt-linux-uclibc/bin/../../../toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33/usr/lib/libgcc_s.a failed
etc.
Looks like the static version of libgcc_s is missing.
Anyway, I changed my package Makefile to:
TARGET_LIBS = -Wl,-Bdynamic -lgcc_s \
-Wl,-Bstatic -lcurl
define Build/Compile
$(TARGET_CONFIGURE_OPTS) \
CFLAGS="$(TARGET_CFLAGS)" \
LDFLAGS="$(TARGET_LDFLAGS)" \
LIBS="$(TARGET_LIBS)" \
$(MAKE) -C $(PKG_BUILD_DIR)
endef
Works for me =)
I understand why linking with a static library would need a static version of its dependencies, But I wasn't expecting the linker to do it behind my back, without falling back the dynamic version first.
Related
I am using this Git for Zbspac.exe
https://github.com/uyjulian/zbspac
And the following for my MinGW Distro:
https://nuwen.net/mingw.html
I have a MinGW distro set up to target my zbspac.exe Makefile. However, I keep getting bounced for
make (e=2): The system cannot find the file specified.
make: *** [Makefile:25: BitStream.o] Error 2
I have BitStream.c and Bitstream.h in the main directory, but it seems the object file doesn't register for the Distro. I feel that it's going to be the same for all the other object files.
My first idea was to create a duplicate file for each .c file into a .o file. This helped clear the issues relating to the .o not being found (although, this solution is probably not ideal). Is there a way to fix this (besides creating duplicate files)?
It then gives me the error
i686-w64-mingw32-gcc -o zbspac.exe BitStream.o ByteArray.o CmdArgs.o FileSystem.o HuffmanDecoder.o HuffmanEncoder.o Logger.o LzssDecoder.o LzssEncoder.o MinHeap.o NexasPacker.o NexasUnpacker.o ScriptPacker.o ScriptUnpacker.o StringUtils.o zbspac.o external/zlib/adler32.o external/zlib/compress.o external/zlib/crc32.o external/zlib/deflate.o external/zlib/gzclose.o external/zlib/gzlib.o external/zlib/gzread.o external/zlib/gzwrite.o external/zlib/infback.o external/zlib/inffast.o external/zlib/inflate.o external/zlib/inftrees.o external/zlib/trees.o external/zlib/uncompr.o external/zlib/zutil.o -static -static-libstdc++ -static-libgcc
process_begin: CreateProcess(NULL, i686-w64-mingw32-gcc -o zbspac.exe BitStream.o ByteArray.o CmdArgs.o FileSystem.o HuffmanDecoder.o HuffmanEncoder.o Logger.o LzssDecoder.o LzssEncoder.o MinHeap.o NexasPacker.o NexasUnpacker.o ScriptPacker.o ScriptUnpacker.o StringUtils.o zbspac.o external/zlib/adler32.o external/zlib/compress.o external/zlib/crc32.o external/zlib/deflate.o external/zlib/gzclose.o external/zlib/gzlib.o external/zlib/gzread.o external/zlib/gzwrite.o external/zlib/infback.o external/zlib/inffast.o external/zlib/inflate.o external/zlib/inftrees.o external/zlib/trees.o external/zlib/uncompr.o external/zlib/zutil.o -static -static-libstdc++ -static-libgcc, ...) failed.
make (e=2): The system cannot find the file specified.
make: *** [Makefile:22: zbspac.exe] Error 2
, which is a self-referential error, since I want to be compiling zbspac.exe, not referring to it.
For reference, the Makefile, which has not been edited:
EXE_TARGET = zbspac.exe
TXTS = License.txt Readme.txt Instructions.txt PackageFormat.txt ScriptTxtFormat.txt
PROJECT_FILE = Makefile .project .cproject
SRC_DIST = zbspac-src.7z
BIN_DIST = zbspac-bin.7z
CC = i686-w64-mingw32-gcc
LD = i686-w64-mingw32-ld
CFLAGS = -O2 -std=c99 -Werror -Wall -pedantic -pedantic-errors -Iexternal/zlib
LIBS = -static -static-libstdc++ -static-libgcc
DIST_MAKE = 7za a
ZLIB_SRCS = external/zlib/adler32.c external/zlib/compress.c external/zlib/crc32.c external/zlib/deflate.c external/zlib/gzclose.c external/zlib/gzlib.c external/zlib/gzread.c external/zlib/gzwrite.c external/zlib/infback.c external/zlib/inffast.c external/zlib/inflate.c external/zlib/inftrees.c external/zlib/trees.c external/zlib/uncompr.c external/zlib/zutil.c
SRCS = $(wildcard *.c) $(ZLIB_SRCS)
HEADERS = $(wildcard *.h)
OBJS = $(patsubst %.c, %.o, $(SRCS))
all: $(EXE_TARGET)
$(EXE_TARGET): $(OBJS)
$(CC) -o $(EXE_TARGET) $(OBJS) $(LIBS)
%.o: %.c
$(CC) $(CFLAGS) -c -o $# $<
src_dist: $(SRC_DIST)
bin_dist: $(BIN_DIST)
$(SRC_DIST): $(SRCS) $(HEADERS) $(TXTS) $(PROJECT_FILE)
$(DIST_MAKE) $(SRC_DIST) $(SRCS) $(HEADERS) $(TXTS) $(PROJECT_FILE)
$(BIN_DIST): $(EXE_TARGET) $(TXTS)
$(DIST_MAKE) $(BIN_DIST) $(EXE_TARGET) $(TXTS)
.PHONY: clean
clean:
$(RM) $(OBJS) $(EXE_TARGET) $(SRC_DIST) $(BIN_DIST)
How do I solve this?
Hello I can't make my Makefile working with
$(CC) $(CFLAGS) $(INC) $(OBJS) $(MLX_LNK) -o $(NAME).
got a
clang -O3 -Wall -Wextra -Werror -I -I cub3d.h src/cub3d.o src/checks/argvcheck.o src/checks/parse_map.o src/libft/basics.o src/libft/basics_bis.o src/libft/get_next_line.o src/utils/errors.o -L minilibx_opengl -lmlx -framework OpenGL -framework AppKit -o cub3D
clang: error: cannot specify -o when generating multiple output files
make: *** [cub3D] Error 1
The command on terminal I do is "make test1"
I also tried with $(CC) $(CFLAGS) -I $(HEADER) $(OBJS) $(MLX_LNK) -o $(NAME).
but got
Compiling...
clang -O3 -Wall -Wextra -Werror -I cub3d.h src/cub3d.o src/checks/argvcheck.o src/checks/parse_map.o src/libft/basics.o src/libft/basics_bis.o src/libft/get_next_line.o src/utils/errors.o -L minilibx_opengl -lmlx -framework OpenGL -framework AppKit -o cub3D
Undefined symbols for architecture x86_64:
"_init_cube", referenced from:
_init_game in cub3d.o
"_write_errors", referenced from:
_verify_line in argvcheck.o
_ft_parse_cub in argvcheck.o
_my_get_next_line in get_next_line.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Many thanks for your help
Makefile here :
NAME = cub3D
HEADER = cub3d.h
CC = clang
CFLAGS = -O3 -Wall -Wextra -Werror
INC = -I $(MLX-DIR) -I $(HEADER)
MLX_DIR = minilibx_opengl
MLX_LNK = -L $(MLX_DIR) -lmlx -framework OpenGL -framework AppKit
SRCS = src/main.c \
src/checks/argvcheck.c \
src/libft/basics.c \
src/libft/get_next_line.c \
src/utils/errors.c \
OBJS = $(SRCS.c=.o)
all: $(NAME)
mlx: $(MLX-DIR)
#echo "\033[34m-= Making libX.a... =-"
#make -C $(MLX_DIR)
$(NAME): ${OBJS} mlx
$(CC) $(CFLAGS) $(INC) $(OBJS) $(MLX_LNK) -o $(NAME)
test1: $(NAME)
$(NAME) ; ./a.out maps/test1.cub
clean:
#echo "\033[0;31mCleaning..."
rm -f $(OBJS)
# + $(B_OBJ)
# + rm -f bitmap.bmp
#echo "\033[0m"
fclean: clean
#echo "\033[34m-= Cleaning mlx... =-"
#make clean -C $(MLX_DIR)
#echo "\033[0;31mRemoving executable..."
rm -f $(NAME)
#echo "\033[0m"
re: fclean all
.PHONY: all clean fclean re
````
Well, first of all this is wrong:
OBJS = $(SRCS.c=.o)
You're missing a : here, it should be $(SRCS:.c=.o) As a result, OBJS will be empty.
Next, this is not causing you problems at the moment but is not right: you should always use $(MAKE) never a raw command like make when invoking a sub-make.
Finally, the way you've written your question by embedding results into the middle of the makefile makes it very hard to read. Please put the makefile first, then separate sections for different attempts at recipes. And you need to include the command line that make printed out (cut and paste the exact line please!) for us to see what the command being run it (with all variables expanded). Typically it becomes VERY obvious what the problem is if you look at that.
For example in this case you'd see that there are actually no object files in the link line, so it should be clear that the $(OBJS) variable is not being set properly.
EDIT
OK, thanks for showing the command line. Now, you should look at it carefully and you will see your problem :). Look at this here:
clang -O3 -Wall -Wextra -Werror -I -I cub3d.h src/cub3d.o ...
Does that look right to you? Look specifically at -I -I cub3d.h... does that seem right?
What happens is that the compiler expects a pathname to come after the -I and there isn't one, so it treats the second -I as the pathname. Then the file cub3d.h is treated as a source file, and you can't link a source file with object files.
So why does this look like this? Look at your makefile:
INC = -I $(MLX-DIR) -I $(HEADER)
so the missing thing is where $(MLX-DIR) goes. What is that variable? Well you have this:
MLX_DIR = minilibx_opengl
but this is not the same thing because it uses an underscore whereas the reference uses a dash. So, make them the same.
Then you'll see that it's not valid to put a file as an argument to -I. That takes a directory to search for header files. If you want to include the header you have to add #include "cub3d.h" in your source code, not add it to the compile line.
Im trying to develop application in C using Bluez library on linux. I cant figure out how to properly pass
all include paths to compiler so that all libraries I need will be visible.
No matter what I try I get following errors:
cc -g -I<PATH_TO_BLUEZ>/bluez-5.54/ -I/usr/include/glib-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include/ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include/ -ldbus-1 -ldbus-glib-1 -c -o disc_gdbus.o disc_gdbus.c
cc -o myprog disc_gdbus.o -I<PATH_TO_BLUEZ>/bluez-5.54/ -I/usr/include/glib-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include/ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include/ -ldbus-1 -ldbus-glib-1
disc_gdbus.o: In function `print_chrc':
<PATH_TO_APP>/disc_gdbus.c:98: undefined reference to `bt_uuidstr_to_str'
disc_gdbus.o: In function `print_desc':
<PATH_TO_APP>/disc_gdbus.c:120: undefined reference to `bt_uuidstr_to_str'
collect2: error: ld returned 1 exit status
Makefile:15: recipe for target 'myprog' failed
make: *** [myprog] Error 1
I need to include following files:
#include <glib.h>
#include "src/shared/util.h"
#include "src/shared/queue.h"
#include "src/shared/io.h"
#include "src/shared/shell.h"
#include "gdbus/gdbus.h"
Function bt_uuidstr_to_str is in directory <PATH_TO_BLUEZ>/bluez-5.54/src/shared/util.h. So it should be seen.
In the makefile I include everything like this:
INC=-I<PATH_TO_BLUEZ>/bluez-5.54/ \
-I/usr/include/glib-2.0 \
-I/usr/include/dbus-1.0 \
-I/usr/lib/x86_64-linux-gnu/dbus-1.0/include/ \
-I/usr/lib/x86_64-linux-gnu/glib-2.0/include/ \
-ldbus-1 \
-ldbus-glib-1 \
src = disc_gdbus.c
obj = $(src:.c=.o)
CFLAGS=-g $(INC) $(LIBS)
myprog: $(obj)
$(CC) -o $# $^ $(CFLAGS)
.PHONY: clean
clean:
rm -f $(obj) myprog
I studied ways to modify include path, and this method should allow linker to see all relevant files, but somehow it does not.
I supplied those include paths to VS Code and they worked without problems:
{
"C_Cpp.default.includePath": [
"<PATH_TO_BLUEZ>/bluez-5.54/**",
"/usr/include/glib-2.0"
],
}
Which leaves me even more puzzled. I spent already multiple hours on this and I have no idea why those includes do not work.
I am trying to successful execute a make file that comes from a new crytpo-coin called Sia Coin. It can be found here Sia Coin GPU Miner. It's relatively new and so some stuff requires more manual installation. I was getting the following error on Ubuntu 16.04 when using the make file. CL/cl.h was missing, and I was able to install and it is located at /usr/include/nvidia-361/CL/cl.h. However, when I ran the make file I still get errors so I think I need to include this path someone in the Make file, the problem is I am not familiar with make files at all. Below is the Make file I need to edit to include the path for compilation:
ifeq ($(shell uname -s),Darwin)
CC ?= clang
LDLIBS += -lcurl -framework OpenCL
else
CC ?= gcc
LDLIBS += -lOpenCL -lcurl
endif
CFLAGS += -c -std=c11 -Wall -pedantic -O2
TARGET = sia-gpu-miner
SOURCES = sia-gpu-miner.c network.c
OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
all: $(TARGET)
%.o: %.c
$(CC) $(CFLAGS) -o $# $<
$(TARGET): $(OBJECTS)
$(CC) -o $# $^ $(LDLIBS)
clean:
rm -f $(TARGET) $(OBJECTS)
.PHONY: all clean
Any help toward solving this problem is greatly appreciated.
Edit:
A new message I am getting now adding
CFLAGS += -c -std=c11 -Wall -pedantic -O2 -I /usr/include/nvidia-361
is now:
-lOpenCL -lcurl /usr/bin/ld: cannot find -lOpenCL collect2: error: ld returned 1 exit status
Two files did compile:
sia-gpu-miner.c
network.c
But I don't know enough to know why the -lOpenCL is not found. No ld directory exists in that directory location in the error if that helps.
Try changing
CFLAGS += -c -std=c11 -Wall -pedantic -O2
to
CFLAGS += -c -std=c11 -Wall -pedantic -O2 -I /usr/include/nvidia-361
I have a makefile. When I run it on Unix I get this error:
cc -I/opt/oracle/product/9.2.0/rdbms/demo -I/opt/oracle/product/9.2.0/rdbms/public \
-I/opt/oracle/product/9.2.0/plsql/public \
-I/opt/oracle/product/9.2.0/network/public -I../common -I../include -I. \
-L/opt/oracle/product/9.2.0/lib -L/opt/oracle/product/9.2.0/rdbms/lib -L../../lib \
-g -errwarn=%all -Xt -lclntsh -ldl -Bstatic -lclient9 -lvsn9 -lcommon9 -lgeneric9 \
-lmm -lcore9 -lnls9 -lwssmbx -ldes -lnsl -lsocket -lgen -lm -o bessToWss
usage: cc [ options] files. Use 'cc -flags' for details
*** Error code 1
What does "usage: cc [ options] files. Use 'cc -flags' for details" mean?
I'm not sure why I get the error because I do use cc -flags:
$(TARGET_DIR)/bessToWss: $(INTFOBJS)
cc $(CFLAGS) $(INTFOBJS) $(OCISHAREDLIBS) -o $#
EDIT: Adding my entire makefile
ORACLE_HOME=/opt/oracle/product/9.2.0
COMMON_SRC=../common
BNS_INCLUDE=../include
LIBHOME=$(ORACLE_HOME)/lib/
RDBMSLIB=$(ORACLE_HOME)/rdbms/lib/
WSSLIBS =-lwssmbx -ldes
LLIBRDBMS_CLT =-lclient9 -lvsn9 -lcommon9 -lgeneric9 -lmm
LLIBCLNTSH =-lclntsh -ldl
CORELIBS =-lcore9 -lnls9
LDLIBS =-lnsl -lsocket -lgen -lm
EXSYSLIBS =-R $(ORACLE_HOME)/lib
STATICTTLIBS =$(LLIBRDBMS_CLT) $(CORELIBS) $(WSSLIBS) $(LDLIBS)
OCISHAREDLIBS =$(LLIBCLNTSH) -Bstatic $(STATICTTLIBS)
LDFLAGS =-L$(ORACLE_HOME)/lib -L$(ORACLE_HOME)/rdbms/lib -L../../lib
INCLUDE =-I$(ORACLE_HOME)/rdbms/demo -I$(ORACLE_HOME)/rdbms/public -I$(ORACLE_HOME)/plsql/public -I$(ORACLE_HOME)/network/public -I$(COMMON_SRC) -I$(BNS_INCLUDE) -I.
CFLAGS =$(INCLUDE) $(LDFLAGS) -g -errwarn=%all -Xt
BESSOBJS=bessToWss.o
COMMONLIST=$(COMMON_SRC)/oracle.c \
$(COMMON_SRC)/logger.c
INTFOBJS=$(BESSOBJS) $(COMMONLIST)
$(TARGET_DIR)/bessToWss: $(INTFOBJS)
cc $(CFLAGS) $(INTFOBJS) $(OCISHAREDLIBS) -o $#
clean:
$(RM) *.o
It means you have an invalid compiler option on the command line. It might be that you are using the 'wrong' compiler (maybe GCC instead of Sun's compiler, for example). The probable problem options I see are:
-Xt
-errwarn=%all
and maybe (but probably not)
-Bstatic
The others would not lead to usage errors like that.
(NB: It would help to identify the machine and the compiler you are using, and the compiler Oracle expects you to use.)
It looks like you don't have any object files to actually link together. The $(INTFOBJS) variable is likely empty. Along with potentially having the wrong flags, this would also cause it to fail.