views:

849

answers:

4

The following issue popped up in my open source library, and I can't figure out what's going on.

Two of my users have (gcc) compiler errors that look like:

/home/someone/Source/src/._regex.cpp:1:1: warning: null character(s) ignored
/home/someone/Source/src/._regex.cpp:1: error: stray ‘\5’ in program
/home/someone/Source/src/._regex.cpp:1: error: stray ‘\26’ in program
/home/someone/Source/src/._regex.cpp:1: error: stray ‘\7’ in program
/home/someone/Source/src/._regex.cpp:1:5: warning: null character(s) ignored
/home/someone/Source/src/._regex.cpp:1: error: stray ‘\2’ in program
...

I can't reproduce these errors; the code compiles fine on all machines I've tested.

Googling around seemed to indicate that this is often a result of a strange encoding or strange formatting, but I ran all the source through a hex editor, and all characters are either printable ASCII (0x20 - 0x7E), or tab, or newline. That's it.

Also, both users successfully compiled the previous version of the library; but the particular file in question (regex.cpp) and its header files haven't been modified since that time!

Please see here for more details, including links to download the code if you want. But I'd be happy with just a pointer in a possible direction.

A: 

Could be a corrupt file on their part.

What's on line 1 of _regex.cpp on THEIR system.

If there was a download / encoding issue you'll have to look at what's in the files on their system, not what's in your code repository.

Glen
+13  A: 

The errors are in ._regex.cpp, not regex.cpp. Files staring with ._ are autogenerated by MacOS. It seems your build system tries to compile all files ending with .cpp. It probably shouldn't compile anything starting with a dot.

Baffe Boyois
These .+ files are created by OSX on a non HFS+ (Mac OS native format) filesystem
Mark
+4  A: 

Baffe Boyois has got the right general answer - your CMake rules must be doing too much.

On MacOS X 10.5.8 (Leopard), I get:

Osiris JL: cmake ..
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/jleffler/tmp/yaml-cpp-0.2.3/build
Osiris JL: make
Scanning dependencies of target yaml-cpp
[  2%] Building CXX object CMakeFiles/yaml-cpp.dir/src/._conversion.cpp.o
/tmp/yaml-cpp-0.2.3/src/._conversion.cpp:1:1: warning: null character(s) ignored
/tmp/yaml-cpp-0.2.3/src/._conversion.cpp:1: error: stray ‘\5’ in program
/tmp/yaml-cpp-0.2.3/src/._conversion.cpp:1: error: stray ‘\22’ in program
/tmp/yaml-cpp-0.2.3/src/._conversion.cpp:1: error: stray ‘\7’ in program
/tmp/yaml-cpp-0.2.3/src/._conversion.cpp:1:5: warning: null character(s) ignored
/tmp/yaml-cpp-0.2.3/src/._conversion.cpp:1: error: stray ‘\2’ in program
/tmp/yaml-cpp-0.2.3/src/._conversion.cpp:1:7: warning: null character(s) ignored
/tmp/yaml-cpp-0.2.3/src/._conversion.cpp:1:17: warning: null character(s) ignored
...

You should list the files you need compiled; you should not just compile all and sundry.

The problem seems to be in CMakeLists.txt:

file(GLOB public_headers include/*.h)
file(GLOB private_headers src/*.h)
file(GLOB sources src/*.cpp)

Either the CMake GLOB is a bit too enthusiastic (I'm using version 2.6-patch 4) or you cannot afford to use it while any of your customers are using MacOS X.

What the GLOB is doing expanding to include files starting with '.' is anyone's guess; I'd be inclined to regard it as a bug in cmake.

However, as a workaround, I edited CMakeLists.txt and got this to work:

file(GLOB public_headers include/[a-z]*.h)
file(GLOB private_headers src/[a-z]*.h)
file(GLOB sources src/[a-z]*.cpp)

This isn't the complete solution: I ran into a continuation of the problem with the code in the yaml-reader directory. I modified the yaml-reader/CMakeLists.txt file in basically the same way.

FWIW:

$ file ._*
._conversion.cpp: AppleDouble encoded Macintosh file
._exp.cpp:        AppleDouble encoded Macintosh file
._map.cpp:        AppleDouble encoded Macintosh file
._map.h:          AppleDouble encoded Macintosh file
._node.cpp:       AppleDouble encoded Macintosh file
._null.cpp:       AppleDouble encoded Macintosh file
._ostream.cpp:    AppleDouble encoded Macintosh file
._parser.cpp:     AppleDouble encoded Macintosh file
._regex.cpp:      AppleDouble encoded Macintosh file
._regeximpl.h:    AppleDouble encoded Macintosh file
._scanner.cpp:    AppleDouble encoded Macintosh file
._scanner.h:      AppleDouble encoded Macintosh file
._scanscalar.cpp: AppleDouble encoded Macintosh file
._scanscalar.h:   AppleDouble encoded Macintosh file
._sequence.cpp:   AppleDouble encoded Macintosh file
._simplekey.cpp:  AppleDouble encoded Macintosh file
._stream.cpp:     AppleDouble encoded Macintosh file
._token.h:        AppleDouble encoded Macintosh file
$ odx ._con*.cpp 
0x0000: 00 05 16 07 00 02 00 00 4D 61 63 20 4F 53 20 58   ........Mac OS X
0x0010: 20 20 20 20 20 20 20 20 00 02 00 00 00 09 00 00           ........
0x0020: 00 32 00 00 00 79 00 00 00 02 00 00 00 AB 00 00   .2...y..........
0x0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
*
0x0050: 00 00 00 00 41 54 54 52 00 3C E0 2B 00 00 00 AB   ....ATTR.<.+....
0x0060: 00 00 00 9C 00 00 00 0F 00 00 00 00 00 00 00 00   ................
0x0070: 00 00 00 00 00 00 00 01 00 00 00 9C 00 00 00 0F   ................
0x0080: 00 00 17 63 6F 6D 2E 61 70 70 6C 65 2E 54 65 78   ...com.apple.Tex
0x0090: 74 45 6E 63 6F 64 69 6E 67 00 00 00 55 54 46 2D   tEncoding...UTF-
0x00A0: 38 3B 31 33 34 32 31 37 39 38 34                  8;134217984
0x00AB:
$

One odd detail - some of the files in the 'src' directory do not have the shadow files. When I do 'tar -tvf yaml-cpp-0.2.3.tar.gz', I see the files being shipped with the source:

Osiris JL: tar -tvf yaml-cpp-0.2.3.tar.gz
drwxr-xr-x beder/staff       0 2009-10-22 15:13:52 ./
-rw-r--r-- beder/staff    1750 2009-10-22 15:09:05 ./CMakeLists.txt
drwxr-xr-x beder/staff       0 2009-10-19 16:40:15 ./include/
-rw-r--r-- beder/staff     171 2009-09-06 13:41:54 ./include/._conversion.h
-rw-r--r-- beder/staff    1118 2009-09-06 13:41:54 ./include/conversion.h
-rw-r--r-- beder/staff     302 2009-07-29 15:25:23 ./include/crt.h
-rw-r--r-- beder/staff    2254 2009-10-19 16:40:14 ./include/emitter.h
-rw-r--r-- beder/staff    1660 2009-10-19 16:40:14 ./include/emittermanip.h
-rw-r--r-- beder/staff     171 2009-08-18 22:07:22 ./include/._exceptions.h
-rw-r--r-- beder/staff    5638 2009-08-18 22:07:22 ./include/exceptions.h
-rw-r--r-- beder/staff     765 2009-07-29 15:25:23 ./include/iterator.h
-rw-r--r-- beder/staff     444 2009-07-29 15:25:23 ./include/mark.h
-rw-r--r-- beder/staff     171 2009-09-06 12:25:12 ./include/._node.h
-rw-r--r-- beder/staff    3467 2009-09-06 12:25:12 ./include/node.h
-rw-r--r-- beder/staff     171 2009-09-15 20:54:20 ./include/._nodeimpl.h
...
-rw-r--r-- beder/staff     171 2009-07-29 21:28:26 ./include/._yaml.h
-rw-r--r-- beder/staff     321 2009-07-29 21:28:26 ./include/yaml.h
-rw-r--r-- beder/staff     167 2009-09-05 16:01:06 ./._install.txt
-rw-r--r-- beder/staff     652 2009-09-05 16:01:06 ./install.txt
-rw-r--r-- beder/staff    1073 2009-05-29 19:31:21 ./license.txt
drwxr-xr-x beder/staff       0 2009-10-22 14:49:11 ./src/
-rw-r--r-- beder/staff    1697 2009-08-24 16:28:46 ./src/aliascontent.cpp
-rw-r--r-- beder/staff    1171 2009-08-24 16:28:46 ./src/aliascontent.h
-rw-r--r-- beder/staff     112 2009-05-29 19:31:21 ./src/content.cpp
-rw-r--r-- beder/staff    1557 2009-08-24 16:28:46 ./src/content.h
-rw-r--r-- beder/staff     171 2009-09-06 13:31:56 ./src/._conversion.cpp
-rw-r--r-- beder/staff    2027 2009-09-06 13:31:56 ./src/conversion.cpp
...

So the miscreant files are being shipped with the product tar file. You got infected somewhere - not sure how.

Jonathan Leffler
[^.]*.cpp ought to work as well
bdonlan
@bdonlan: yes, it would work - but how many source files don't start with an alphabetic character? Granted, your notation is more compact if any files start with upper-case too. I still think there is room to argue that there's a bug in cmake - shell globbing does not expand to match names starting with dot, and neither should cmake.
Jonathan Leffler
Nice catch. What seems bizarre to me is that the previous version compiled fine for them. What is in the `._whatever.cpp` generated files?
Jesse Beder
Running: 'rm -f */._*' in the top-level directory where the software is extracted allows the build to work with unmodified cmake files.
Jonathan Leffler
It turns out these extra hidden files are auto-generated by the tar command, and do *not* actually exist on my system. They're a result of "extended attributes" of OS X; I managed to get rid of them, and bundled only the actual source in a new tarball. Thanks for your help!
Jesse Beder
Well, I'm not sure how you got the extended attributes added. My testing, FWIW, was on MacOS X 10.5.8 (Leopard). With various attempts, I didn't get to see those '._*' files generated on my disk, nor were they created by the GNU tar (1.15.1) from /usr/bin or /usr/local/bin (yes, one day I'll work out why I have both). So, you're probably right that something kicks MacOS X into creating them and then tar correctly archives them; I'm just not convinced it is tar doing the damage. But I don't have a good explanation for what is doing the damage. Are you using some GUI (Xcode, perhaps)?
Jonathan Leffler
Yeah, it looks like if you save a file in Xcode (or in TextEdit, or probably anything GUI-y), it adds these crazy extended attributes. I spent a while figuring out how to deal with them - see http://superuser.com/questions/61185/why-do-i-get-files-like-foo-in-my-tarball-on-os-x for more info
Jesse Beder
A: 

Make sure you only have .o files in your build directory. I had this issue and the cause was an error in my Makefile (actually it was an scons file) that built one source file to a .c file instead of a .o file. The resulting file was a binary, but I'm assuming gcc tried to interpret it as a .c file.

Ben Gartner