Chris Tonkinson Chris Tonkinson - 8 months ago 53
Linux Question

Variations of sed between OSX and GNU/Linux

I've got a makefile (developed for gmake on Linux) that I'm attempting to port to OSX, but it seems like sed doesn't want to cooperate. What I do is use GCC to autogenerate dependency files, and then tweak them a bit using sed. The relevant portion of the makefile:

$(OBJ_DIR)/%.d: $(SRC_DIR)/%.cpp
$(CPPC) -MM -MD $< -o $@
sed -i 's|\(.*\)\.o:|$(OBJ_DIR)/\1.o $(OBJ_DIR)/\1.d $(TEST_OBJ_DIR)/\1_utest.o:|' $@

While this runs with no trouble under GNU/Linux, I get errors like the following when attempting to build on OSX:

sed: 1: "test/obj/equipmentConta ...": undefined label 'est/obj/equipmentContainer_utest.d'
sed: 1: "test/obj/dice_utest.d": undefined label 'est/obj/dice_utest.d'
sed: 1: "test/obj/color-string_u ...": undefined label 'est/obj/color-string_utest.d'

It would seem like sed is chopping off a character, but I can't see the solution.


OS X sed handles the -i argument differently to the Linux version.

You can probably generate a command that will work for both by adding -e:

#      vv
sed -i -e 's|\(.*\)\.o:|$(OBJ_DIR)/\1.o $(OBJ_DIR)/\1.d $(TEST_OBJ_DIR)/\1_utest.o:|' $@

It's because OS X sed -i interprets the next thing after the -i as a file extension for a backup copy of the in-place edit. (Probably the Linux version only does this if there is no space between the -i and the extension.)

The upshot of this is that sed consumes the s||| as the extension (!) then interprets the next argument as a command - in this case it begins with t, which sed recognises as a branch-to-label command expecting the target label as an argument - hence the error you see.

If you create a file testyou can reproduce the error on OS X:

$ sed -i 's|x|y|' test
sed: 1: "test": undefined label 'est'