0

I'm trying to code a printf clone. I've built a library file called "libftprintf.a" but when I try to use it, I get the following error, on Mac OSX 10.8.5:

ld: warning: ignoring file ./libftprintf.a, file was built for archive which is not the architecture being linked (x86_64): ./libftprintf.a

Strangely this works fine (but I need only one lib called libftprintf, so this is not acceptable):

gcc -Wall -Wextra -Werror -I libft/includes/ -o ft_printf_test.bin -L libft -lft -L. -lftprintf ft_printf_test.c

I suspect I have misused the ar command to link both libs together. But I don't se my mistake yet.

What could be the cause of that?

Everything seems to compile just fine until I try to use the libftprintf.a file with the make test command. I've searched for a solution on Google, but most answers relate to XCode only. According to lipo -info, the files are x86_64.

My GCC version:

$> gcc --version
Configured with: --prefix=/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix

Below is the full output of my makefile, for reference.

$> make re
make -C libft clean
rm -f src/ft_arrdel.o src/ft_atoi.o src/ft_bzero.o src/ft_isalnum.o src/ft_isalpha.o src/ft_isascii.o src/ft_isdigit.o src/ft_islower.o src/ft_isprint.o src/ft_isupper.o src/ft_itoa.o src/ft_lstadd.o src/ft_lstdel.o src/ft_lstdelone.o src/ft_lstiter.o src/ft_lstmap.o src/ft_lstnew.o src/ft_lstpush.o src/ft_malloc.o src/ft_memalloc.o src/ft_memccpy.o src/ft_memchr.o src/ft_memcmp.o src/ft_memcpy.o src/ft_memdel.o src/ft_memmove.o src/ft_memset.o src/ft_putchar.o src/ft_putchar_fd.o src/ft_putendl.o src/ft_putendl_fd.o src/ft_putnbr.o src/ft_putnbr_fd.o src/ft_putstr.o src/ft_putstr_fd.o src/ft_strcat.o src/ft_strchr.o src/ft_strclr.o src/ft_strcmp.o src/ft_strcpy.o src/ft_strdel.o src/ft_strdup.o src/ft_strequ.o src/ft_striter.o src/ft_striteri.o src/ft_strjoin.o src/ft_strlcat.o src/ft_strlen.o src/ft_strmap.o src/ft_strmapi.o src/ft_strncat.o src/ft_strncmp.o src/ft_strncpy.o src/ft_strnequ.o src/ft_strnew.o src/ft_strnstr.o src/ft_strrchr.o src/ft_strrev.o src/ft_strsplit.o src/ft_strstr.o src/ft_strsub.o src/ft_strtrim.o src/ft_tolower.o src/ft_toupper.o src/get_next_line.o
rm -f ft_printf.o
make -C libft fclean
rm -f src/ft_arrdel.o src/ft_atoi.o src/ft_bzero.o src/ft_isalnum.o src/ft_isalpha.o src/ft_isascii.o src/ft_isdigit.o src/ft_islower.o src/ft_isprint.o src/ft_isupper.o src/ft_itoa.o src/ft_lstadd.o src/ft_lstdel.o src/ft_lstdelone.o src/ft_lstiter.o src/ft_lstmap.o src/ft_lstnew.o src/ft_lstpush.o src/ft_malloc.o src/ft_memalloc.o src/ft_memccpy.o src/ft_memchr.o src/ft_memcmp.o src/ft_memcpy.o src/ft_memdel.o src/ft_memmove.o src/ft_memset.o src/ft_putchar.o src/ft_putchar_fd.o src/ft_putendl.o src/ft_putendl_fd.o src/ft_putnbr.o src/ft_putnbr_fd.o src/ft_putstr.o src/ft_putstr_fd.o src/ft_strcat.o src/ft_strchr.o src/ft_strclr.o src/ft_strcmp.o src/ft_strcpy.o src/ft_strdel.o src/ft_strdup.o src/ft_strequ.o src/ft_striter.o src/ft_striteri.o src/ft_strjoin.o src/ft_strlcat.o src/ft_strlen.o src/ft_strmap.o src/ft_strmapi.o src/ft_strncat.o src/ft_strncmp.o src/ft_strncpy.o src/ft_strnequ.o src/ft_strnew.o src/ft_strnstr.o src/ft_strrchr.o src/ft_strrev.o src/ft_strsplit.o src/ft_strstr.o src/ft_strsub.o src/ft_strtrim.o src/ft_tolower.o src/ft_toupper.o src/get_next_line.o
rm -f libft.a
rm -f libftprintf.a
rm -Rf ft_printf_test.bin*
gcc -Wall -Wextra -Werror -I libft/includes/ -c ft_printf.c -o ft_printf.o
make -C libft
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_arrdel.c -o src/ft_arrdel.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_atoi.c -o src/ft_atoi.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_bzero.c -o src/ft_bzero.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_isalnum.c -o src/ft_isalnum.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_isalpha.c -o src/ft_isalpha.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_isascii.c -o src/ft_isascii.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_isdigit.c -o src/ft_isdigit.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_islower.c -o src/ft_islower.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_isprint.c -o src/ft_isprint.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_isupper.c -o src/ft_isupper.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_itoa.c -o src/ft_itoa.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_lstadd.c -o src/ft_lstadd.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_lstdel.c -o src/ft_lstdel.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_lstdelone.c -o src/ft_lstdelone.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_lstiter.c -o src/ft_lstiter.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_lstmap.c -o src/ft_lstmap.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_lstnew.c -o src/ft_lstnew.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_lstpush.c -o src/ft_lstpush.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_malloc.c -o src/ft_malloc.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_memalloc.c -o src/ft_memalloc.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_memccpy.c -o src/ft_memccpy.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_memchr.c -o src/ft_memchr.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_memcmp.c -o src/ft_memcmp.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_memcpy.c -o src/ft_memcpy.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_memdel.c -o src/ft_memdel.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_memmove.c -o src/ft_memmove.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_memset.c -o src/ft_memset.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_putchar.c -o src/ft_putchar.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_putchar_fd.c -o src/ft_putchar_fd.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_putendl.c -o src/ft_putendl.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_putendl_fd.c -o src/ft_putendl_fd.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_putnbr.c -o src/ft_putnbr.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_putnbr_fd.c -o src/ft_putnbr_fd.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_putstr.c -o src/ft_putstr.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_putstr_fd.c -o src/ft_putstr_fd.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strcat.c -o src/ft_strcat.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strchr.c -o src/ft_strchr.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strclr.c -o src/ft_strclr.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strcmp.c -o src/ft_strcmp.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strcpy.c -o src/ft_strcpy.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strdel.c -o src/ft_strdel.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strdup.c -o src/ft_strdup.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strequ.c -o src/ft_strequ.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_striter.c -o src/ft_striter.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_striteri.c -o src/ft_striteri.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strjoin.c -o src/ft_strjoin.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strlcat.c -o src/ft_strlcat.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strlen.c -o src/ft_strlen.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strmap.c -o src/ft_strmap.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strmapi.c -o src/ft_strmapi.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strncat.c -o src/ft_strncat.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strncmp.c -o src/ft_strncmp.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strncpy.c -o src/ft_strncpy.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strnequ.c -o src/ft_strnequ.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strnew.c -o src/ft_strnew.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strnstr.c -o src/ft_strnstr.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strrchr.c -o src/ft_strrchr.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strrev.c -o src/ft_strrev.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strsplit.c -o src/ft_strsplit.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strstr.c -o src/ft_strstr.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strsub.c -o src/ft_strsub.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_strtrim.c -o src/ft_strtrim.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_tolower.c -o src/ft_tolower.o
gcc -g -Wall -Wextra -Werror -I includes -c src/ft_toupper.c -o src/ft_toupper.o
gcc -g -Wall -Wextra -Werror -I includes -c src/get_next_line.c -o src/get_next_line.o
ar -rsv libft.a src/ft_arrdel.o src/ft_atoi.o src/ft_bzero.o src/ft_isalnum.o src/ft_isalpha.o src/ft_isascii.o src/ft_isdigit.o src/ft_islower.o src/ft_isprint.o src/ft_isupper.o src/ft_itoa.o src/ft_lstadd.o src/ft_lstdel.o src/ft_lstdelone.o src/ft_lstiter.o src/ft_lstmap.o src/ft_lstnew.o src/ft_lstpush.o src/ft_malloc.o src/ft_memalloc.o src/ft_memccpy.o src/ft_memchr.o src/ft_memcmp.o src/ft_memcpy.o src/ft_memdel.o src/ft_memmove.o src/ft_memset.o src/ft_putchar.o src/ft_putchar_fd.o src/ft_putendl.o src/ft_putendl_fd.o src/ft_putnbr.o src/ft_putnbr_fd.o src/ft_putstr.o src/ft_putstr_fd.o src/ft_strcat.o src/ft_strchr.o src/ft_strclr.o src/ft_strcmp.o src/ft_strcpy.o src/ft_strdel.o src/ft_strdup.o src/ft_strequ.o src/ft_striter.o src/ft_striteri.o src/ft_strjoin.o src/ft_strlcat.o src/ft_strlen.o src/ft_strmap.o src/ft_strmapi.o src/ft_strncat.o src/ft_strncmp.o src/ft_strncpy.o src/ft_strnequ.o src/ft_strnew.o src/ft_strnstr.o src/ft_strrchr.o src/ft_strrev.o src/ft_strsplit.o src/ft_strstr.o src/ft_strsub.o src/ft_strtrim.o src/ft_tolower.o src/ft_toupper.o src/get_next_line.o
ar: creating archive libft.a
a - src/ft_arrdel.o
a - src/ft_atoi.o
a - src/ft_bzero.o
a - src/ft_isalnum.o
a - src/ft_isalpha.o
a - src/ft_isascii.o
a - src/ft_isdigit.o
a - src/ft_islower.o
a - src/ft_isprint.o
a - src/ft_isupper.o
a - src/ft_itoa.o
a - src/ft_lstadd.o
a - src/ft_lstdel.o
a - src/ft_lstdelone.o
a - src/ft_lstiter.o
a - src/ft_lstmap.o
a - src/ft_lstnew.o
a - src/ft_lstpush.o
a - src/ft_malloc.o
a - src/ft_memalloc.o
a - src/ft_memccpy.o
a - src/ft_memchr.o
a - src/ft_memcmp.o
a - src/ft_memcpy.o
a - src/ft_memdel.o
a - src/ft_memmove.o
a - src/ft_memset.o
a - src/ft_putchar.o
a - src/ft_putchar_fd.o
a - src/ft_putendl.o
a - src/ft_putendl_fd.o
a - src/ft_putnbr.o
a - src/ft_putnbr_fd.o
a - src/ft_putstr.o
a - src/ft_putstr_fd.o
a - src/ft_strcat.o
a - src/ft_strchr.o
a - src/ft_strclr.o
a - src/ft_strcmp.o
a - src/ft_strcpy.o
a - src/ft_strdel.o
a - src/ft_strdup.o
a - src/ft_strequ.o
a - src/ft_striter.o
a - src/ft_striteri.o
a - src/ft_strjoin.o
a - src/ft_strlcat.o
a - src/ft_strlen.o
a - src/ft_strmap.o
a - src/ft_strmapi.o
a - src/ft_strncat.o
a - src/ft_strncmp.o
a - src/ft_strncpy.o
a - src/ft_strnequ.o
a - src/ft_strnew.o
a - src/ft_strnstr.o
a - src/ft_strrchr.o
a - src/ft_strrev.o
a - src/ft_strsplit.o
a - src/ft_strstr.o
a - src/ft_strsub.o
a - src/ft_strtrim.o
a - src/ft_tolower.o
a - src/ft_toupper.o
a - src/get_next_line.o
ar -rsv libftprintf.a libft/libft.a ft_printf.o
ar: creating archive libftprintf.a
a - libft/libft.a
a - ft_printf.o
ranlib libftprintf.a
$> make test
gcc -Wall -Wextra -Werror -I libft/includes/ -L. -lftprintf -o ft_printf_test.bin ft_printf_test.c
ld: warning: ignoring file ./libftprintf.a, file was built for archive which is not the architecture being linked (x86_64): ./libftprintf.a
Undefined symbols for architecture x86_64:
  "_ft_printf_string", referenced from:
      _test_printf_percent in ft_printf_test-jTXeph.o
  "_ft_strcmp", referenced from:
      _test_printf_percent in ft_printf_test-jTXeph.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [test] Error 1
[ ckleines ~/Projects/2013-2014/Algo-1/printf ] $> lipo -info libft/libft.a
input file libft/libft.a is not a fat file
Non-fat file: libft/libft.a is architecture: x86_64
[ ckleines ~/Projects/2013-2014/Algo-1/printf ] $> lipo -info libftprintf.a
input file libftprintf.a is not a fat file
Non-fat file: libftprintf.a is architecture: x86_64
[ ckleines ~/Projects/2013-2014/Algo-1/printf ] $> lipo -info ft_printf.o
Non-fat file: ft_printf.o is architecture: x86_64
conradkleinespel
  • 6,560
  • 10
  • 51
  • 87
  • Are you trying to use it on the same machine you compiled the lib? – kratenko Dec 18 '13 at 16:45
  • If you move `-L. -lftprintf` to be *after* the file arguments, does that help? http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options says "It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified." – Mark Plotnick Dec 18 '13 at 16:51
  • Yes. Everything on the same machine. Strangely, if I do `gcc -I libft/includes/ ft_printf_test.c ft_printf.c libft/libft.a`, it compiles and runs just fine. @MarkPlotnick: Moving -L. -lftprintf after the file arguments does not help. – conradkleinespel Dec 18 '13 at 16:56
  • I don't see you specifying architecture flags to `gcc` (`-arch=xxx`). That will help, no doubt. – trojanfoe Dec 18 '13 at 17:02
  • @trojanfoe: With `gcc -Wall -Wextra -Werror -I libft/includes/ -arch x86_64 -o ft_printf_test.bin -L. -lftprintf ft_printf_test.c`, I get the same error. With `-arch=x86_64`, `clang: error: argument unused during compilation: '-arch=x86_64'`. – conradkleinespel Dec 18 '13 at 17:08
  • Did you recompile the library as well? – trojanfoe Dec 18 '13 at 17:20
  • It doesn't compile with `arch=x86_64`. I get the error: `clang: error: argument unused during compilation: '-arch=x86_64'.` I've recompiled everything on the Mac I'm using. And I get the error described in the post above. – conradkleinespel Dec 18 '13 at 17:30
  • I've updated my question, adding that this works fine, strangely: `gcc -Wall -Wextra -Werror -I libft/includes/ -o ft_printf_test.bin -L libft -lft -L. -lftprintf ft_printf_test.c`. But since the goal is to have only one lib called `libftprintf.a`, this is not acceptable to me. – conradkleinespel Dec 18 '13 at 17:33
  • why not just include the architecture that the file was built for when you compile? – l'L'l Dec 18 '13 at 17:54
  • As I have said previously: When I add the arch flag, I get an error. In addition, everything was compiled on the same machine today (no updates between compilations whatsoever). – conradkleinespel Dec 18 '13 at 18:03
  • I wonder if `ld` is upset with `libftprintf.a` because you have an archive within an archive. If you populate `libftprintf.a` with all the individual .o files rather than with `libft.a`, that might fix things. – Mark Plotnick Dec 19 '13 at 12:08

3 Answers3

4

Use libtool -static -o instead of ar.

Static library link issue with Mac OS X: symbol(s) not found for architecture x86_64

Community
  • 1
  • 1
prosseek
  • 182,215
  • 215
  • 566
  • 871
2

I've found a slightly dirty but working solution for now. I extract the libft/libft.a archive in a temporary directory. Link the new library with the extracted .o files and then remove the temporary directory.

$(NAME): $(OBJ) $(HEADER)
    make -C libft
    mkdir libft_o && cd libft_o && ar -x ../libft/libft.a && cd ..
    $(AR) $(NAME) libft_o/*.o $(OBJ)
    rm -Rf libft_o
    ranlib $(NAME)

The drawback being that if an object file from libft at some point has the same name than one from the printf files, it will overwrite things. But that's not likely to happen.

conradkleinespel
  • 6,560
  • 10
  • 51
  • 87
1

If you have fat architecture object files you must make sure that you pass the s flag to ar. Without it the linker will refuse to take archive files that contain fat architecture .o files. For example:

$ ar rcs libprintf.a *.o

You should then see a warning about creating a 'fat archive'. Don't worry about this, it means that ar won't be able to update the archive file, but the linker will be able to use it to link properly.

Will
  • 4,585
  • 1
  • 26
  • 48